[英]Should I temporarily disable foreign key constraints? How?
我有两张桌子:
person:
id serial primary key,
name varchar(64) not null
task:
tenant_id integer not null references person (id) on delete cascade,
customer_id integer not null references person (id) on delete restrict
(他们有比这更多的列,但其余的与问题无关。)
问题是,我想级联删除task
时,其承租人person
将被删除。 但是当租户和客户是同一个人时, customer_id
外键约束将限制删除。
我的问题有两个部分:
实际上你创造了一个矛盾规则的竞争条件 。
我的第一个冲动是检查DEFERRED
约束是否有帮助。 但它没有任何区别是有道理的。
我发现在CREATE TABLE
脚本中首先出现的FK约束是这场比赛的胜利者。 如果ON DELETE CASCADE
首先出现,则删除是级联的,如果ON DELETE RESTRICT
先出现,则操作中止。
考虑一下SQL Fiddle的演示。
这似乎与目录表pg_constraint
较小的oid
相关:
SELECT oid, * FROM pg_constraint WHERE conrelid = 'task'::regclass
但是你的反馈表明,这不是原因。 也许pg_attribute.attnum
决定比赛。 无论哪种方式,只要它没有记录的行为,你就不能依赖它在下一个主要版本中保持这种状态。 可能值得在pgsql-general@postgresql.org上发布一个问题。
独立于所有这些,你需要考虑其他行:即使CASCADE
在一个同时具有tenant_id
和customer_id
指向某person
task
中的行中,如果任何行只有customer_id
引用person
,它仍将受到限制。
另一个SQL小提琴演示案例。
你最好的选择是放弃并重新创建它。 在事务中完成所有操作以确保您不会破坏参照完整性。
BEGIN;
ALTER TABLE task DROP CONSTRAINT task_customer_id_fkey;
DELETE FROM person WHERE id = 3;
ALTER TABLE task ADD CONSTRAINT task_customer_id_fkey
FOREIGN KEY (customer_id) REFERENCES person (id) ON DELETE RESTRICT;
COMMIT;
这将独占锁定表,不适合在多用户环境中进行常规使用。
我怎么知道约束的名字 ? 我从pg_constraint
演示的pg_constraint
了它。 可能更容易使用显式约束名称开头:
CREATE TEMP TABLE task (
customer_id integer NOT NULL
,tenant_id integer NOT NULL REFERENCES person (id) ON DELETE CASCADE
,CONSTRAINT task_customer_id_fkey FOREIGN KEY (customer_id)
REFERENCES person (id) ON DELETE RESTRICT
);
还有
ALTER TABLE task DISABLE trigger ALL;
更多在手册中 。 但这会禁用所有触发器。 我没有运气试图仅禁用系统创建的触发器来实现单个FK约束。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.