Szukałem już od jakiegoś czasu, ale nie mogę znaleźć łatwego rozwiązania mojego problemu. Chciałbym zduplikować rekord w tabeli, ale oczywiście unikalny klucz podstawowy wymaga aktualizacji.
Mam to zapytanie:
INSERT INTO invoices
SELECT * FROM invoices AS iv WHERE iv.ID=XXXXX
ON DUPLICATE KEY UPDATE ID = (SELECT MAX(ID)+1 FROM invoices)
Problem w tym, że to po prostu zmienia ID
wiersz zamiast go kopiować. Czy ktoś wie, jak to naprawić?
// edycja: Chciałbym to zrobić bez wpisywania wszystkich nazw pól, ponieważ nazwy pól mogą się zmieniać w czasie.
CREATE TEMPORARY TABLE tmp SELECT bla FROM invoices WHERE bla; UPDATE tmp SET id=NULL; INSERT INTO invoices SELECT * FROM tmp;
NOT NULL
ustawione naid
. Zastanawiałem się tylko, czy masz sugestie dotyczące tego przypadku. Czy jest to uważane za złą praktykę?Odpowiedź Alexa wymaga uwagi (np. Blokowanie lub transakcja) w środowiskach z wieloma klientami.
Zakładając, że
AUTO ID
pole jest pierwsze w tabeli (zwykły przypadek), możemy skorzystać z niejawnych transakcji.Z dokumentacji MySQL:
źródło
NULL
lub0
oba są dopuszczalne. Czy możesz opublikować zrzuty ekranu problemu, powielając je i udostępniając tutaj.invoices
zawieraID
pole AUTO_INCREMENT . Tabela źródłowatmp
nie. Aby uzyskać wymaganą korelację 1: 1 podczas wstawiania, określasz0
jako pierwsze pole selekcji, które jest polem AUTO_INCREMENT tabeli docelowej. Dotmp.*
wybiera wszystkie pola z tabeli źródłowejtmp
. Idealny! Masz teraz swoją korelację 1: 1. Świetna odpowiedź @Tim.NULL
i0
to nie to samo. Bieżący kontekst jest włączonyAUTO_INCREMENT
. W takich polach nie można wstawiać wartości0
aniNULL
. Ale kiedy ich używać jako wejścia do takiego zakresu, następna wartość sekwencja zostanie przypisana do tego pola auto matycznie. I stąd mój komentarz. Dowód na SQL Fiddle: sqlfiddle.com/#!9/d619f/1WIESZ na pewno, że DUPLICATE KEY zostanie wyzwolony, dlatego możesz wcześniej wybrać MAX (ID) +1:
INSERT INTO invoices SELECT MAX(ID)+1, ... other fields ... FROM invoices AS iv WHERE iv.ID=XXXXX
źródło
Twoje podejście jest dobre, ale problem polega na tym, że zamiast wpisywania nazw pól używasz "*". Jeśli umieścisz wszystkie nazwy kolumn z wyjątkiem klucza podstawowego, skrypt będzie działał jak urok na jednym lub wielu rekordach.
INSERT INTO invoices (iv.field_name, iv.field_name,iv.field_name ) SELECT iv.field_name, iv.field_name,iv.field_name FROM invoices AS iv WHERE iv.ID=XXXXX
źródło
Późna odpowiedź, którą znam, ale wciąż jest to częste pytanie, chciałbym dodać kolejną odpowiedź, że zadziałało dla mnie, z użyciem tylko jednej
insert into
instrukcji liniowej i myślę, że jest to proste, bez tworzenia nowej tabeli (ponieważ być problemem zCREATE TEMPORARY TABLE
uprawnieniami):INSERT INTO invoices (col_1, col_2, col_3, ... etc) SELECT t.col_1, t.col_2, t.col_3, ... t.updated_date, FROM invoices t;
Rozwiązanie działa dla
AUTO_INCREMENT
kolumny id, w przeciwnym razie możesz dodaćID
kolumnę również do instrukcji:INSERT INTO invoices (ID, col_1, col_2, col_3, ... etc) SELECT MAX(ID)+1, t.col_1, t.col_2, t.col_3, ... etc , FROM invoices t;
Jest to naprawdę łatwe i proste, możesz zaktualizować cokolwiek innego w jednym wierszu bez drugiego oświadczenia o aktualizacji na później (np. Zaktualizować kolumnę tytułu dodatkowym tekstem lub zastąpić ciąg innym), a także możesz dokładnie określić, co dokładnie chcesz powielić, jeśli wszystko to jest to, jeśli niektórzy, możesz to zrobić.
źródło
INSERT into wp_options SELECT NULL, 'theme_mods_twopress', option_value, autoload FROM wp_options where option_name = 'theme_mods_onepress';
kopiowałem, zwiększając wpis (AUTO_INCREMENT
NULL
sztuczka z góry) ioption_name
pole.Chciałem tylko rozszerzyć wspaniałą odpowiedź Alexa, aby była odpowiednia, jeśli chcesz zduplikować cały zestaw rekordów:
SET @x=7; CREATE TEMPORARY TABLE tmp SELECT * FROM invoices; UPDATE tmp SET id=id+@x; INSERT INTO invoices SELECT * FROM tmp;
Po prostu musiałem to zrobić i uznałem odpowiedź Alexa za doskonały punkt wyjścia !. Oczywiście musisz ustawić @x na najwyższy numer wiersza w tabeli (jestem pewien, że możesz to złapać za pomocą zapytania). Jest to przydatne tylko w tej bardzo specyficznej sytuacji, więc zachowaj ostrożność, jeśli nie chcesz powielać wszystkich wierszy. W razie potrzeby dostosuj matematykę.
źródło
Mam podobny problem i oto co robię:
insert into Preguntas (`EncuestaID`, `Tipo` , `Seccion` , `RespuestaID` , `Texto` ) select '23', `Tipo`, `Seccion`, `RespuestaID`, `Texto` from Preguntas where `EncuestaID`= 18
Były Preguntas:
CREATE TABLE IF NOT EXISTS `Preguntas` ( `ID` int(11) unsigned NOT NULL AUTO_INCREMENT, `EncuestaID` int(11) DEFAULT NULL, `Tipo` char(5) COLLATE utf8_unicode_ci DEFAULT NULL, `Seccion` int(11) DEFAULT NULL, `RespuestaID` bigint(11) DEFAULT NULL, `Texto` text COLLATE utf8_unicode_ci , PRIMARY KEY (`ID`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=522 ;
Tak więc
ID
jest automatycznie zwiększana, a także używam stałej wartości („23”)EncuestaID
.źródło
Ja też tego potrzebowałem; moim rozwiązaniem było użycie SQLYOG (wersja bezpłatna) do wyeksportowania żądanego rekordu jako SQL (tworzy wkładkę).
Następnie ręcznie zmodyfikowałem to, aby usunąć identyfikator, ponieważ musi on zostać wygenerowany automatycznie, a następnie skopiowałem wstawkę do SQLYog, aby go wykonać. To było bezbolesne. Myślę, że wiele innych graficznych interfejsów MySQL może to zrobić.
Dzięki temu otrzymuję rekord, którego mogę użyć do celów testowych w działającym systemie.
Teraz mam również tę wkładkę do ponownego wykorzystania, ponieważ tabela jest przepisywana codziennie.
źródło
Niewielkie odchylenie, główna różnica polega na ustawieniu pola klucza podstawowego („nazwa_zmiennej”) na wartość null, co powoduje wyświetlenie ostrzeżenia, ale działa. Ustawiając klucz podstawowy na null, automatyczne zwiększanie wartości działa podczas wstawiania rekordu do ostatniej instrukcji.
Ten kod czyści również poprzednie próby i może być uruchamiany więcej niż raz bez problemów:
DELETE FROM `tbl` WHERE varname="primary key value for new record"; DROP TABLE tmp; CREATE TEMPORARY TABLE tmp SELECT * FROM `tbl` WHERE varname="primary key value for old record"; UPDATE tmp SET varname=NULL; INSERT INTO `tbl` SELECT * FROM tmp;
źródło