Дублировать/копировать записи в одной таблице 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: Я хотел бы сделать это, не набирая все имена полей, потому что имена полей могут меняться со временем.
Ответы
Ответ 1
Обычно я использую временную таблицу. Это, вероятно, не вычислительно эффективно, но, похоже, работает нормально! Здесь я дублирую запись 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;
Надеюсь, что все будет хорошо для вас!
Ответ 2
Ответ Alex требует некоторой осторожности (например, блокировки или транзакции) в средах с несколькими клиентами.
Предполагая, что поле 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 столбцу для генерации порядковых номеров.
Ответ 3
Вы точно знаете, что DUPLICATE KEY активируется, поэтому вы можете заранее выбрать MAX (ID) +1:
INSERT INTO invoices SELECT MAX(ID)+1, ... other fields ... FROM invoices AS iv WHERE iv.ID=XXXXX
Ответ 4
Ваш подход хорош, но проблема в том, что вы используете "*" вместо того, чтобы набирать имена полей. Если вы поместите все имена колонок excep primary key, ваш script будет работать как прелесть на одной или нескольких записях.
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
Ответ 5
Мне тоже это нужно; моим решением было использовать SQLYOG (бесплатную версию) для экспорта нужной записи в виде SQL (создает вставку).
Затем я отредактировал это, чтобы удалить идентификатор, поскольку это необходимо автогенерировать, а затем скопировать вставку в SQLYog для ее выполнения. Это было безболезненно. Думаю, многие другие графические интерфейсы MySQL тоже могут это сделать.
Это дает мне запись, которую я могу использовать для тестирования в живой системе.
Теперь у меня есть эта вставка для повторного использования, так как таблица перезаписывается ежедневно.
Ответ 6
У меня подобная проблема, и я хочу, чтобы я делал
insert into Preguntas (`EncuestaID`, `Tipo` , `Seccion` , `RespuestaID` , `Texto` ) select '23', `Tipo`, `Seccion`, `RespuestaID`, `Texto` from Preguntas where `EncuestaID`= 18
Подготовлено:
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
Ответ 7
Я просто хотел продлить Alex отличный ответ, чтобы сделать его подходящим, если вам захочется дублировать весь набор записей:
SET @x=7;
CREATE TEMPORARY TABLE tmp SELECT * FROM invoices;
UPDATE tmp SET [email protected];
INSERT INTO invoices SELECT * FROM tmp;
Я просто должен был сделать это и нашел, что Алекс отвечает на идеальный прыжок! Конечно, вы должны установить @x на самый высокий номер строки в таблице (я уверен, что вы могли бы захватить это с помощью запроса). Это полезно только в этой конкретной ситуации, поэтому будьте осторожны, если вы не хотите дублировать все строки. При необходимости отрегулируйте математику.
Ответ 8
Поздний ответ, который я знаю, но это все еще общий вопрос, я хотел бы добавить еще один ответ: "Это сработало для меня, используя только однострочный оператор 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;
это действительно легко и прямо, вы можете обновить что-нибудь еще в одной строке без какого-либо второго оператора обновления позже (например: обновить столбец заголовка дополнительным текстом или заменить строку другим), также вы можете специфический с тем, что именно вы хотите дублировать, если все, то это, если есть, вы можете это сделать.
Ответ 9
Незначительное изменение, основное отличие заключается в том, чтобы установить поле первичного ключа ( "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;