我是postgresql的新手,对于多列唯一约束有疑问。
尝试向表中添加行时出现此错误:
ERROR: duplicate key value violates unique constraint "i_rb_on"
DETAIL: Key (a_fk, b_fk)=(296, 16) already exists.
我使用了这段代码(简短版):
INSERT INTO rb_on (a_fk, b_fk) SELECT a.pk, b.pk FROM A, B WHERE NOT EXISTS (SELECT * FROM rb_on WHERE a_fk=a.pk AND b_fk=b.pk);
i_rb_on
是唯一约束/列(a_fk, b_fk)
。
我的WHERE NOT EXISTS
似乎没有针对此类唯一密钥的重复密钥错误提供保护。
更新:
INSERT INTO tabA (mark_done, log_time, tabB_fk, tabC_fk)
SELECT FALSE, '2003-09-02 04:05:06', tabB.pk, tabC.pk FROM tabB, tabC, tabD, tabE, tabF
WHERE (tabC.sf_id='SUMMER' AND tabC.sf_status IN(0,1)
AND tabE.inventory_status=0)
AND tabF.tabD_fk=tabD.pk
AND tabD.tabE_fk=tabE.pk
AND tabE.tabB_fk=tabB.pk
AND tabF.tabC_fk=tabC.pk
AND NOT EXISTS (SELECT *
FROM tabA
WHERE tabB_fk=tabB.pk AND tabC_fk=tabC.pk);
在tabA唯一索引中:
CREATE UNIQUE INDEX i_tabA
ON tabA
USING btree
(tabB_fk , tabC_fk );
必须在tabA中插入一行(多行)。
答案 0 :(得分:2)
您的WHERE NOT EXISTS
从不提供针对唯一违规行为的适当保护。它似乎只在大多数时间。 WHERE NOT EXISTS
可以与另一个插入同时运行,因此该行仍然会多次插入,除了其中一个插入之外的所有插入都会导致唯一的违规。
出于这个原因,通常运行插入更好,如果行已经存在则允许违规。
除非您显示数据(如SQL CREATE TABLE
和INSERT
)以及真实查询,否则我无法帮助您解决所描述的确切问题。
A, B
加入。使用A INNER JOIN B ON (...)
。它可以更容易地告诉哪些连接条件应该应用于查询的哪些部分,并且更难忘记连接条件。你似乎已经这样做了;你试图插入一个笛卡尔积。我怀疑这只是查询中的编辑错误。
答案 1 :(得分:0)
我在最后添加了LIMIT 1:... WHERE tabB_fk = tabB.pk AND tabC_fk = tabC.pk)LIMIT1; 它就行了。
我创建了一个LIMIT 1的函数和... EXCEPTION WHEN unique_violation THEN ......它也有效。
但是当使用LIMIT 1和“NOT EXISTS”时,我认为没有必要使用unique_violation错误处理。