Я долго искал, но не могу найти легкого решения своей проблемы. Я хотел бы продублировать запись в таблице, но, конечно, необходимо обновить уникальный первичный ключ.
У меня такой запрос:
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: я хотел бы сделать это, не вводя все имена полей, потому что имена полей могут меняться со временем.
CREATE TEMPORARY TABLE tmp SELECT bla FROM invoices WHERE bla; UPDATE tmp SET id=NULL; INSERT INTO invoices SELECT * FROM tmp;
NOT NULL
установить наid
. Мне просто интересно, есть ли у вас предложения по этому делу. Это считается плохой практикой?Ответ Алекса требует некоторой осторожности (например, блокировки или транзакции) в мультиклиентских средах.
Предполагая, что
AUTO ID
поле является первым в таблице (обычный случай), мы можем использовать неявные транзакции.Из документов MySQL:
источник
NULL
или0
оба являются приемлемыми. Можете ли вы опубликовать скриншоты проблемы, воспроизведя их, и поделиться ими здесь.invoices
содержитID
поле AUTO_INCREMENT . Исходная таблицаtmp
- нет. Чтобы получить необходимую корреляцию 1: 1 во время вставки, вы указываете в0
качестве первого поля выбора, которое является полем AUTO_INCREMENT целевой таблицы. Вtmp.*
выбирает все поля из таблицы источникаtmp
. Отлично! Теперь у вас есть соотношение 1: 1. Замечательный ответ @Tim.NULL
и0
это не одно и то же. Текущий контекст находится вAUTO_INCREMENT
функции. Вы не можете вставить0
илиNULL
значение в такие поля. Но при их использовании в качестве входных данных в такое поле, следующее значение последовательности будет присвоен этой области авто матически. Отсюда и мой комментарий. Доказательство на SQL Fiddle: sqlfiddle.com/#!9/d619f/1Вы точно ЗНАЕТЕ, что сработает DUPLICATE KEY, поэтому вы можете заранее выбрать MAX (ID) +1:
INSERT INTO invoices SELECT MAX(ID)+1, ... other fields ... FROM invoices AS iv WHERE iv.ID=XXXXX
источник
Ваш подход хорош, но проблема в том, что вы используете «*» вместо перечисления имен полей. Если вы поместите все имена столбцов, кроме первичного ключа, ваш скрипт будет работать как шарм на одной или нескольких записях.
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 wp_options SELECT NULL, 'theme_mods_twopress', option_value, autoload FROM wp_options where option_name = 'theme_mods_onepress';
копировал при увеличении записи (AUTO_INCREMENT
NULL
трюк сверху) иoption_name
поля.Я просто хотел расширить отличный ответ Алекса, чтобы сделать его подходящим, если вы хотите продублировать весь набор записей:
SET @x=7; CREATE TEMPORARY TABLE tmp SELECT * FROM invoices; UPDATE tmp SET id=id+@x; INSERT INTO invoices SELECT * FROM tmp;
Мне просто нужно было это сделать, и я нашел ответ Алекса идеальной отправной точкой! Конечно, вы должны установить @x на самый высокий номер строки в таблице (я уверен, что вы могли бы получить это с помощью запроса). Это полезно только в этой очень конкретной ситуации, поэтому будьте осторожны, используя его, если вы не хотите дублировать все строки. При необходимости скорректируйте математические расчеты.
источник
У меня похожая проблема, и я делаю вот что:
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
.источник
Мне это тоже было нужно; Мое решение заключалось в использовании 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;
источник