Множество проблем.
Ваша настройка, расширенная:
CREATE TABLE a (
pk_a int PRIMARY KEY
, a int
, comment text -- added column to make effect clear
);
CREATE TABLE b (
pk_b int PRIMARY KEY
, b int
, comment text
);
INSERT INTO a VALUES (1, 11, 'comment from a')
, (2, 22, 'comment from a');
INSERT INTO b VALUES (1, 77, 'comment from b');
Это работает:
INSERT INTO b (pk_b, b, comment)
SELECT pk_a, a, comment
FROM a
ON CONFLICT (pk_b) DO UPDATE -- conflict is on the unique column
SET b = excluded.b; -- key word "excluded", refer to target column
Результат:
TABLE b;
pk_b | b | comment
------+----+----------------
1 | 11 | comment from b -- updated
2 | 22 | comment from a -- inserted
Проблемы
Вы сбиваете с толку table_aи Aв своей демонстрации (как прокомментировал @Abelisto ).
Использование легальных, строчных, без кавычек идентификаторов помогает избежать путаницы.
Как упоминалось @Ziggy , ON CONFLICTработает только для фактических нарушений уникальных или исключающих ограничений . Руководство:
Необязательное ON CONFLICTпредложение определяет альтернативное действие по отношению к выдаче уникальной ошибки нарушения или нарушения ограничения исключения.
Следовательно, ON CONFLICT (b)не может работать, никаких ограничений нет. ON CONFLICT (pk_b)работает.
Как и в случае @Ziggy , имена исходных таблиц не видны в этой UPDATEчасти. Руководство:
SETИ WHEREположение в ON CONFLICT DO UPDATEимеет доступ к существующей строке с использованием имени таблицы (или псевдонима) и строки , предложенных для вставки с помощью специальной excludedтаблицы .
Жирный акцент мой.
Вы также не можете использовать имена столбцов исходной таблицы в UPDATEдетали. Это должны быть имена столбцов целевой строки . Итак, вы действительно хотите:
SET b = excluded.b
Руководство еще раз:
Обратите внимание, что эффекты всех BEFORE INSERTтриггеров для каждой строки отражаются в исключенных значениях, поскольку эти эффекты могли способствовать исключению строки из вставки.
CREATE TABLE A...создает таблицуa, а неtable_a.