PostgreSQL多列唯一约束导致错误

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)

对于这种类型的唯一键,我的 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中。
2个回答

2
您的WHERE NOT EXISTS并不能完全保护您免受唯一性冲突的影响,虽然大多数情况下看起来是可以的。因为WHERE NOT EXISTS可能会与其他插入操作同时运行,所以该行数据仍然可能被重复插入,而其中除了一个插入操作之外,所有插入操作都会导致唯一性冲突。
因此,通常最好只是运行插入操作,如果该行数据已经存在,则让唯一性冲突发生。
除非您展示数据(作为SQL CREATE TABLEINSERT),以及真实的查询语句,否则我无法帮助您解决描述的确切问题。
顺便说一下,请不要使用旧式的A, B连接方式。使用A INNER JOIN B ON (...)更好。这样可以更容易地确定哪些连接条件应用于查询的哪些部分,并且更难忘记连接条件。您似乎已经这样做了;您试图插入笛卡尔积。我怀疑这只是查询中的编辑错误。

只需运行插入操作,让违规发生:请求宽恕比获得许可更容易。 - mu is too short

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错误处理。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接