3

我是 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)

似乎 myWHERE 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 中。

4

2 回答 2

2

WHERE NOT EXISTS 永远不会针对独特的违规行为提供适当的保护。它似乎只是大多数时候。可以与另一个插入同时WHERE NOT EXISTS运行,因此该行仍被插入多次,并且除了一个插入之外的所有插入都会导致唯一违规。

出于这个原因,如果行已经存在,最好只运行插入并让违规发生。

CREATE TABLE除非您显示数据(如 SQL和INSERTs)和真正的查询,否则我无法帮助您解决所描述的确切问题。

顺便说一句,请不要使用旧式A, B连接。使用A INNER JOIN B ON (...). 它可以更容易地判断哪些连接条件应该应用于查询的哪些部分,并且更难忘记连接条件。你似乎已经这样做了;您正在尝试插入笛卡尔积。我怀疑这只是查询中的编辑错误。

于 2013-09-03T00:37:45.830 回答
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错误处理。

于 2013-09-05T00:11:00.490 回答