Дублировать/копировать записи в одной таблице 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;