默认规则将内容添加到当前操作中 http://www.postgresql.org/docs/current/static/sql-createrule.html:
粗略地说,当执行给定表上的给定命令时,规则会导致执行附加命令。
但是 INSTEAD 规则允许您替换操作:
或者,INSTEAD 规则可以用另一个命令替换给定命令,或者导致命令根本不执行。
所以,我想你想要指定 INSTEAD http://www.postgresql.org/docs/current/static/rules-update.html:
CREATE OR REPLACE RULE ignore_duplicate_inserts AS
ON INSERT TO mytable
WHERE (EXISTS ( SELECT mytable.id
FROM mytable
WHERE mytable.id = new.id)) DO INSTEAD NOTHING;
如果没有 INSTEAD,当您想说“而不是 INSERT,什么都不做”时,您的规则本质上是说“执行 INSERT,然后什么也不做”,并且,AFAIK,DO INSTEAD NOTHING
会那么做。
我不是 PostgreSQL 规则方面的专家,但我认为添加“INSTEAD”应该可行。
UPDATE:感谢阿拉克尼德我们知道 http://www.postgresql.org/docs/9.0/interactive/sql-copy.html#AEN58860:
COPY FROM 将调用任何触发器并检查目标表上的约束。但是,它不会调用规则
所以规则在这种情况下不起作用。但是,触发器在 COPY FROM 期间被触发,因此您可以编写 BEFORE INSERT将返回 NULL 的触发器 http://www.postgresql.org/docs/9.0/interactive/trigger-definition.html当它检测到重复行时:
它可以返回 NULL 以跳过当前行的操作。这指示执行器不执行调用触发器的行级操作(插入或修改特定表行)。
也就是说,我认为你最好使用 araqnid 的“将其全部加载到临时表中,清理它,并将其复制到最终目的地”对于像你这样的批量加载操作来说是一个更明智的解决方案。