带有子查询的PostgreSQL INSERT重复键错误

时间:2014-05-14 16:32:18

标签: sql postgresql

StackOverflow上有一些类似的问题,但它们似乎与我的情况完全不符。我试图批量插入具有复合唯一约束的PostgreSQL表。我创建了一个没有任何约束的临时表(temptable),并在其中加载了数据(可能有一些重复的值)。到目前为止,非常好。

现在,我正在尝试使用唯一索引将数据传输到实际表(realtable)。为此,我使用带有子查询的INSERT语句:

INSERT INTO realtable 
SELECT * FROM temptable WHERE NOT EXISTS (
    SELECT 1 FROM realtable WHERE temptable.added_date = realtable.added_date
                              AND temptable.product_name = realtable.product_name
);

但是,我收到了重复的密钥错误:

ERROR: duplicate key value violates unique constraint "realtable_added_date_product_name_key"
SQL state: 23505
Detail: Key (added_date, product_name)=(20000103, TEST) already exists.

我的问题是,WHERE NOT EXISTS条款不应该阻止这种情况发生吗?我该如何解决?

1 个答案:

答案 0 :(得分:2)

NOT EXISTS子句仅阻止temptable的行与realtable的现有行冲突;它不会阻止temptable的多行相互冲突。这是因为SELECT基于realtable的初始状态计算一次,而不是在插入每一行后重新计算。

一种解决方案是在GROUP BY查询中使用DISTINCT ONSELECT,以省略重复项,例如

INSERT INTO realtable 
SELECT DISTINCT ON (added_date, product_name) * 
FROM temptable WHERE NOT EXISTS (
    SELECT 1 FROM realtable WHERE temptable.added_date = realtable.added_date
                              AND temptable.product_name = realtable.product_name
)
ORDER BY ???; -- this ORDER BY will determine which of a set of duplicates is kept by the DISTINCT ON