INSERT INTO… SELECT для всех столбцов MySQL

119

Я пытаюсь переместить старые данные из:

this_table >> this_table_archive

копирование всех столбцов. Я пробовал это, но не работает:

INSERT INTO this_table_archive (*) VALUES (SELECT * FROM this_table WHERE entry_date < '2011-01-01 00:00:00');

Примечание: таблицы идентичны и используются idв качестве первичного ключа.

рукав моря
источник
1
Дайте определение «не работает». У меня может быть похожая проблема, но я не могу сказать, потому что вы не сказали, в чем была ваша проблема !!
Lightness Races на орбите
Не сломано, просто не работает.
Webmaster G

Ответы:

218

Правильный синтаксис описан в руководстве . Попробуй это:

INSERT INTO this_table_archive (col1, col2, ..., coln)
SELECT col1, col2, ..., coln
FROM this_table
WHERE entry_date < '2011-01-01 00:00:00';

Если столбцы идентификаторов являются столбцами с автоматическим приращением и у вас уже есть некоторые данные в обеих таблицах, тогда в некоторых случаях вы можете захотеть опустить идентификатор из списка столбцов и вместо этого сгенерировать новые идентификаторы, чтобы избежать вставки идентификатора, который уже существует в исходном стол. Если ваша целевая таблица пуста, это не будет проблемой.

Марк Байерс
источник
73

Для синтаксиса это выглядит следующим образом (исключите список столбцов, чтобы неявно означать "все")

INSERT INTO this_table_archive
SELECT *
FROM this_table
WHERE entry_date < '2011-01-01 00:00:00'

Чтобы избежать ошибок первичного ключа, если у вас уже есть данные в архивной таблице

INSERT INTO this_table_archive
SELECT t.*
FROM this_table t
LEFT JOIN this_table_archive a on a.id=t.id
WHERE t.entry_date < '2011-01-01 00:00:00'
  AND a.id is null  # does not yet exist in archive
RichardTheKiwi
источник
6
+1 для левого соединения, чтобы избежать конфликтов первичных ключей.
Хартли Броуди,
23

Дополнение к ответу Марка Байерса:

Иногда вы также хотите вставить жестко запрограммированные детали, иначе может произойти сбой уникального ограничения и т. Д. Поэтому используйте следующее в такой ситуации, когда вы переопределяете некоторые значения столбцов.

INSERT INTO matrimony_domain_details (domain, type, logo_path)
SELECT 'www.example.com', type, logo_path
FROM matrimony_domain_details
WHERE id = 367

Здесь стоимость домена добавлена ​​мной жестко, чтобы избавиться от уникального ограничения.

Pratik
источник
4

вам не нужен double () для бита значений? если не попробуй (хотя должен быть способ получше

insert into this_table_archive (id, field_1, field_2, field_3) 
values
((select id from this_table where entry_date < '2001-01-01'), 
((select field_1 from this_table where entry_date < '2001-01-01'), 
((select field_2 from this_table where entry_date < '2001-01-01'), 
((select field_3 from this_table where entry_date < '2001-01-01'));
Дэниел Кассерли
источник
2
OP использует INSERT INTO .. SELECT FROM, а не INSERT INTO .. VALUES. Отличная особенность.
Lightness Races на орбите