我试图为我的数据库创建一些规则以防止重复插入,但是由于我们也是休眠的,.save()被称为insert xxx RETURNING*
我似乎无法使插入规则在插入返回时发挥良好的作用。

CREATE TABLE test ( aaa int, bbb int);

insert into test VALUES(1, 2);

CREATE RULE "testRule1" AS ON INSERT TO  test
  WHERE EXISTS(SELECT 1 FROM test
                WHERE (aaa, bbb)=(NEW.aaa, NEW.bbb))
  DO INSTEAD NOTHING;

如果我尝试只插入一个条件规则
insert into test VALUES(1, 2);
ERROR:  cannot perform INSERT RETURNING on relation "test"
HINT:  You need an unconditional ON INSERT DO INSTEAD rule with a RETURNING clause.

CREATE RULE "testRule2" AS ON INSERT TO  test
  DO INSTEAD INSERT INTO test VALUES(new.*)
  RETURNING test.*;

如果我试图同时插入有条件和无条件的规则
insert into test VALUES(1, 2);
ERROR:  infinite recursion detected in rules for relation "test"

这是不可能实现与我的设置?

最佳答案

避免插入重复项的正确方法是将字段定义为UNIQUE(或PRIMARY KEY

CREATE TABLE Test (
aaa integer,
bbb integer,
val text, /* The reason why I added this field is explained later */
UNIQUE (aaa,bbb)
)

如果元组已经存在(从数据库接收错误代码是一件好事,正如我最近解释的AA>),插入将失败。
如果错误是不可接受的,或者如果希望在单个insert中插入多个记录而不必关心哪个记录违反了UNIQUE约束,那么正确的语法是使用ON CONFLICT子句。
INSERT INTO Test values (1,1,'Some value')
ON CONFLICT DO NOTHING

基本上,将插入具有唯一元组的第一条记录。即使查询本身尝试插入重复项(如以下情况),也可以兼容:
INSERT INTO Test values (2,2,'Will be inserted'), (2,2,'Will not be inserted')
ON CONFLICT DO NOTHING

当然,这也允许您在同一个查询中使用RETURNING子句。

09-10 02:09
查看更多