如何使 ON CONFLICT 适用于复合外键列?

mar*_*hon 5 postgresql foreign-key exception

我无法ON CONFLICT处理外键为复合的外键列。这是一个例子。

create table foreign_table (
   id_a text    not null,
   id_b text    not null,
   id   integer primary key,
   constraint ft_a_b_key unique (id_a, id_b)
);

create table my_table (
   id          integer,
   ftable_id_a text,
   ftable_id_b text,
   constraint my_table_a_b_fk
      foreign key (ftable_id_a, ftable_id_b) references foreign_table (id_a, id_b)
);
Run Code Online (Sandbox Code Playgroud)

使用此查询:

insert into tcell_test.my_table (id, ftable_id_a, ftable_id_b) 
    values (3, 'a3', 'b3') on conflict do nothing ;
Run Code Online (Sandbox Code Playgroud)

比如说,'a3'不在 中foreign_table,我希望ON CONFLICT能够处理该错误。

相反,我收到错误:

[23503] ERROR: insert or update on table "my_table" 
   violates foreign key constraint "my_table_a_b_fk" 
Detail: Key (ftable_id_a, ftable_id_b)=(a3, b3) 
   is not present in table "foreign_table".
Run Code Online (Sandbox Code Playgroud)

有没有办法纠正这个错误并ON CONFLICT处理错误?

ric*_*yen 5

我想你可能误解了aCONFLICT是什么。ACONFLICT违反了唯一性,基本上不应该添加正在添加的行,因为已经存在具有相同值的另一行。

在您的示例中insert into tcell_test.my_table (id, ftable_id_a, ftable_id_b) values (3, 'a3', 'b3') on conflict do nothing;ON CONFLICT永远不会达到条件,因为您没有主键或唯一约束my_table

edb=# alter table my_table add primary key (ftable_id_a,ftable_id_b);
ALTER TABLE
edb=# insert into my_table (id, ftable_id_a, ftable_id_b) 
    values (3, 'a3', 'b3') on conflict do nothing ;
INSERT 0 1
edb=# insert into my_table (id, ftable_id_a, ftable_id_b) 
    values (3, 'a3', 'b3') on conflict do nothing ;
INSERT 0 0
edb=# select * from my_table ;
 id | ftable_id_a | ftable_id_b 
----+-------------+-------------
  3 | a3          | b3
(1 row)
Run Code Online (Sandbox Code Playgroud)

正如您在上面的示例中看到的,我的第二次插入my_table没有执行任何操作,因为存在主键冲突。如果我省略该ON CONFLICT子句,我会得到:

edb=# insert into my_table (id, ftable_id_a, ftable_id_b) 
    values (3, 'a3', 'b3');
ERROR:  duplicate key value violates unique constraint "my_table_pkey"
DETAIL:  Key (ftable_id_a, ftable_id_b)=(a3, b3) already exists.
Run Code Online (Sandbox Code Playgroud)

您在原始帖子 ( ) 中提到的消息ERROR: insert or update on table "my_table" violates foreign key constraint "my_table_a_b_fk"涉及外键违规(而不是主键/唯一性违规)。当and中应该有一行但实际上没有时,就会发生这种违规。数据库期望该行存在,因为您已经定义了该引用(换句话说,取决于)。由于该行不存在于 中,因此插入失败。首先,插入到,然后您可以插入到:foreign_tableid_a=a3id_b=b3my_tableforeign_tablemy_tableforeign_tableforeign_tablemy_tableforeign_tablemy_table

edb=# insert into my_table (id, ftable_id_a, ftable_id_b) 
    values (3, 'a3', 'b3') on conflict do nothing ;
ERROR:  insert or update on table "my_table" violates foreign key constraint "my_table_a_b_fk"
DETAIL:  Key (ftable_id_a, ftable_id_b)=(a3, b3) is not present in table "foreign_table".
edb=# insert into foreign_table values ('a3','b3',1);
INSERT 0 1
edb=# select * from foreign_table ;
 id_a | id_b | id 
------+------+----
 a3   | b3   |  1
(1 row)
edb=# insert into my_table (id, ftable_id_a, ftable_id_b) 
    values (3, 'a3', 'b3') on conflict do nothing ;
INSERT 0 1
edb=# select * from my_table ;
 id | ftable_id_a | ftable_id_b 
----+-------------+-------------
  3 | a3          | b3
(1 row)
Run Code Online (Sandbox Code Playgroud)

  • 对于外键违规,是否有与“冲突时不执行任何操作”类似的功能? (3认同)