Дублировать / копировать записи в той же таблице MySQL
Я искал некоторое время теперь, но я не могу найти простое решение для моей проблемы. Я хотел бы продублировать запись в таблице, но, конечно, уникальный первичный ключ должен быть обновлен.
у меня есть этот запрос:
INSERT INTO invoices
SELECT * FROM invoices AS iv WHERE iv.ID=XXXXX
ON DUPLICATE KEY UPDATE ID = (SELECT MAX(ID)+1 FROM invoices)
проблема в том, что это просто меняет ID
строки вместо копирования строки. Кто-нибудь знает как это исправить ?
/ / edit: я хотел бы сделать это без ввода всех имен полей, потому что поле имена могут меняться с течением времени.
9 ответов:
то, как я обычно делаю это, использует временную таблицу. Это, вероятно, не вычислительно эффективно, но, кажется, работает нормально! Здесь я дублирую запись 99 полностью, создавая запись 100.
CREATE TEMPORARY TABLE tmp SELECT * FROM invoices WHERE id = 99; UPDATE tmp SET id=100 WHERE id = 99; INSERT INTO invoices SELECT * FROM tmp WHERE id = 100;
надеюсь, что это работает нормально для вас!
ответ Алекса требует некоторой осторожности (например, блокировка или транзакция) в многопользовательских средах.
предполагая, что
AUTO ID
поле является первым в таблице (обычный случай), мы можем использовать неявное операции.CREATE TEMPORARY TABLE tmp SELECT * from invoices WHERE ...; ALTER TABLE tmp drop ID; # drop autoincrement field # UPDATE tmp SET ...; # just needed to change other unique keys INSERT INTO invoices SELECT 0,tmp.* FROM tmp; DROP TABLE tmp;из документов MySQL:
использование AUTO_INCREMENT: вы также можете явно назначить NULL или 0 столбцу для создания порядковых номеров.
вы точно знаете, что дубликат ключа сработает, поэтому вы можете заранее выбрать MAX(ID)+1:
INSERT INTO invoices SELECT MAX(ID)+1, ... other fields ... FROM invoices AS iv WHERE iv.ID=XXXXX
ваш подход хорош, но проблема в том, что вы используете "*" вместо включения имен полей. Если вы поместите все имена столбцов excep primary key, ваш скрипт будет работать как шарм на одной или нескольких записях.
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
поздний ответ я знаю, но это все еще общий вопрос, я хотел бы добавить еще один ответ, что он работал для меня, используя только одну строку
insert into
заявление, и я думаю, что это прямо вперед, без создания какой-либо новой таблицы (так как это может быть проблема сCREATE TEMPORARY TABLE
разрешения):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;
решение работает для
AUTO_INCREMENT
столбец ID, в противном случае, вы можете добавитьID
столбец также к заявлению: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;
это действительно легко и прямо вперед, вы можете обновить что-либо еще в одной строке без какого-либо второго оператора обновления для более позднего времени (например: обновить столбец заголовка дополнительным текстом или заменить строку другим), также вы можете указать, что именно вы хотите дублировать, если все это так, если некоторые, вы можете это сделать.
у меня есть аналогичная проблема, и это то, что я делаю
insert into Preguntas (`EncuestaID`, `Tipo` , `Seccion` , `RespuestaID` , `Texto` ) select '23', `Tipo`, `Seccion`, `RespuestaID`, `Texto` from Preguntas where `EncuestaID`= 18
Была 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 ;
Итак,
ID
автоматически увеличивается, а также я использую фиксированное значение ('23`) для' EncuestaID
Я просто хотел расширить отличный ответ Алекса, чтобы сделать его подходящим, если вы хотите дублировать весь набор записей:
SET @x=7; CREATE TEMPORARY TABLE tmp SELECT * FROM invoices; UPDATE tmp SET id=id+@x; INSERT INTO invoices SELECT * FROM tmp;
Я просто должен был сделать это и нашел ответ Алекса идеальным прыжком с точки!. Конечно, вы должны установить @x на самый высокий номер строки в таблице (я уверен, что вы можете захватить это с помощью запроса). Это полезно только в этой конкретной ситуации, поэтому будьте осторожны, используя его, когда вы не хотите дублировать все строки. Отрегулируйте математику как необходимый.
Мне это тоже было нужно; мое решение состояло в том, чтобы использовать SQLYOG (бесплатная версия) для экспорта нужной записи в качестве SQL (создает вставку).
затем я вручную отредактировал это, чтобы удалить идентификатор, поскольку он должен быть автоматически сгенерирован, а затем скопировал вставку в SQLYog для ее выполнения. Это было безболезненно. Я думаю, что многие другие графические интерфейсы MySQL также могут это сделать.
Это дает мне запись, которую я могу использовать для тестирования в живой системе.
теперь у меня есть эта вставка для повторное использование также, как таблица переписывается ежедневно.
небольшое изменение, основное отличие заключается в том, чтобы установить поле первичного ключа ("varname") в null, которое выдает предупреждение, но работает. Установив первичный ключ в значение null, автоинкремент работает при вставке записи в последний оператор.
этот код также очищает предыдущие попытки, и может быть запущен более одного раза без проблем:
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;