我正在尝试为数据库创建一些规则以防止重复插入,但是由于我们也处于休眠状态,因此.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;
如果我尝试仅插入1条条件规则
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"
这是我的设置无法实现的吗?
答案 0 :(得分:1)
避免插入重复项的正确方法是将字段定义为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)
)
如果元组已经存在,插入将失败,并显示错误代码(如我最近here所述,从数据库接收错误代码是一件好事)。
如果出现错误是不可接受的,或者您想在单个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
子句。