ON DUPLICATE KEY UPDATE не срабатывает при несовпадающих названиях полей в исходной и целевой таблицах

CREATE TABLE `contacts` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `marital_status` tinyint(1) DEFAULT NULL,
 PRIMARY KEY (`id`),
) 
ENGINE=MyISAM DEFAULT CHARSET=utf8

CREATE TABLE `anketa` (
 `id` int(11) NOT NULL DEFAULT '0',
 `marital_status_id` int(11) DEFAULT NULL,
 PRIMARY KEY (`id`),
) 
ENGINE=MyISAM DEFAULT CHARSET=utf8

Почему не работает вставка выбранного значения со следующим кодом:

INSERT INTO `contacts` (`marital_status`) 
    SELECT `marital_status_id` 
    FROM `anketa` 
    WHERE `id`=215409 
ON DUPLICATE KEY UPDATE 
    `marital_status` = VALUES(`marital_status`)

И чем по смыслу отличается такой вариант кода (разница в самой концовке, тоже не срабатывает):

INSERT INTO `contacts` (`marital_status`) 
    SELECT `marital_status_id` 
    FROM `anketa` 
    WHERE `id`=215409 
ON DUPLICATE KEY UPDATE 
    `marital_status` = `marital_status_id`";

Имеющиеся в документации пояснения не помогают. Что я не учёл?

P.S. нашел ошибку - "нечаянно" удалил из запроса уникальное поле (id) - после его возвращения заработало:

INSERT INTO `contacts` (`id`, `marital_status`) 
    SELECT `id`, `marital_status_id` 
    FROM `anketa` 
    WHERE `id`=215409 
ON DUPLICATE KEY UPDATE 
    `id` = VALUES(`id`), 
    `marital_status` = VALUES(`marital_status`)

Ответы (1 шт):

Автор решения: Akina

Почему INSERT INTO `contacts` (`id`, `marital_status`) ... может работать, а INSERT INTO `contacts` (`marital_status`) ... нет?

Предположение только одно. id является NOT NULL полем, у которого не указано DEFAULT значение (в т.ч. автогенерируемое). Это и приводит к ошибке.


Почему INSERT INTO `contacts` (`id`, `marital_status`) ... ON DUPLICATE KEY UPDATE ... может и вставлять, и обновлять, а INSERT INTO `contacts` (`marital_status`) ... ON DUPLICATE KEY UPDATE ... всегда вставляет?

ON DUPLICATE KEY UPDATE интересует только нарушение ограничения уникальности.

Если второй вариант не приводит к ошибке, значит, поле id объявлено как AUTO_INCREMENT, и для него генерируется уникальное значение. Поскольку у ODKU прописано UPDATE `marital_status` = VALUES(`marital_status`), то это поле не уникально. Итого - никакого дублирования в принципе нет, и у ODKU нет оснований для срабатывания и обновления.


чем по смыслу отличается такой вариант кода

В первом варианте `marital_status` = VALUES(`marital_status`) полю при обновлении присваивается то значение, которое было бы в него вставлено, если бы не было ошибки дублирования.

Во втором варианте `marital_status` = `marital_status_id` полю просто присваивается значение из другого поля той же записи.

marital_status_id и marital_status - поля из разных таблиц – Simply One

В таком случае этот вариант синтаксически некорректен. В ODKU нельзя ссылаться на поля таблицы-источника - они уже недоступны. ODKU - это фактически триггер. Ссылаться можно только на поля обновляемой таблицы - если брать аналогию с триггером, то просто поле есть поле из OLD, а поле-аргумент функции VALUES() - поле из NEW.

→ Ссылка