Как вставить... выбрать с помощью ключа дублирования
У меня есть две таблицы с одинаковой структурой. Таблица A содержит все текущие объявления, таблица B содержит архивированные объявления. Столбец 1 (ad_id) - это первичный ключ, AI, INT. Настольный движок MyISAM.
Мне нужно скопировать всю таблицу объявлений A, предшествующих определенной дате, в архив, таблица B. Моя цель состоит в том, чтобы все поля, кроме ad_id, дублировались, ad_id должен автоматически увеличиваться. Вот что я пытался:
INSERT INTO B`(`ad_id`, `ad_advertiser`, `ad_ln`, `ad_expire`)
SELECT *
FROM A
WHERE YEAR( ad_expire ) <= 2012
Таблица B содержит много тысяч объявлений, таблица A достаточно часто сбрасывается, так что поле уникального идентификатора имеет низкие числа, которые часто дублируют идентификаторы в таблице B. Таким образом, MySQL отбрасывает шаткий сигнал и говорит, что у меня есть Duplicate entry '8577' for key 'PRIMARY'
,
Итак, я сделал несколько попыток, чтобы обойти это:
Сначала я попытался выбрать отдельные столбцы для вставки, настройки ad_id
в NULL:
INSERT INTO B(`ad_id`, `ad_advertiser`, `ad_ln`, `ad_expire`)
SELECT (NULL, `ad_advertiser`, `ad_ln`, `ad_expire`)
FROM A
WHERE YEAR( ad_expire ) <= 2012
Это приводит к ошибке #1241 - Operand should contain 1 column(s)
, который исчезает, если я использую селектор подстановочного знака *, но затем я получаю ошибку дубликата.
Далее я попробовал SELECT LAST_INSERT_ID()
, который всегда возвращает 0.
Затем я попробовал несколько, используя ON DUPLICATE KEY UPDATE
, но я не могу заставить это работать.
Я даже пытался получить самый высокий идентификатор с:
SELECT @max := max(ad_id) FROM B;
INSERT INTO B`(`ad_id`, `ad_advertiser`, `ad_ln`, `ad_expire`)
SELECT *
FROM A
WHERE YEAR( ad_expire ) <= 2012
ON DUPLICATE KEY UPDATE ad_id = @max + 1
Это работает ровно для одной строки, а затем приводит к дублированию записи (поскольку @max является статической переменной).
Что я здесь не так делаю? Я делаю этот путь слишком сложным?
2 ответа
В вашем случае почему бы не использовать?
INSERT INTO B(`ad_advertiser`, `ad_ln`, `ad_expire`)
SELECT (`ad_advertiser`, `ad_ln`, `ad_expire`)
FROM A
WHERE YEAR( ad_expire ) <= 2012
Вы можете удалить ограничение первичного ключа на вашем ad_id
вашей table B
используя следующую команду.
ALTER TABLE B DROP PRIMARY KEY
Затем попробуйте ваш обычный запрос, т.е.
INSERT INTO B`(`ad_id`, `ad_advertiser`, `ad_ln`, `ad_expire`)
SELECT *
FROM A
WHERE YEAR( ad_expire ) <= 2012
ОБНОВЛЕНИЕ 1
если вы не хотите иметь несколько ad_id
тогда вы можете напрямую попробовать этот запрос
INSERT INTO `B`(`ad_id`, `ad_advertiser`, `ad_ln`, `ad_expire`)
SELECT *
FROM A
WHERE YEAR( ad_expire ) <= 2012
ON DUPLICATE KEY UPDATE
ad_advertiser = VALUES(ad_advertiser),
ad_ln = VALUES(ad_ln),
ad_expire = VALUES(ad_expire);
Вот SQL Fiddle