外键约束的条件CASCADE操作?

时间:2013-08-20 13:54:00

标签: sql postgresql triggers foreign-keys sql-delete

我有parentchild表,其中child有一个FK指向父表的PK。当我删除父表中的某些内容时,我可以通过ON DELETE CASCADE删除子记录。

但是,在我的parent表中,我根本不删除记录。相反,我设置了列state = "passive"。我想删除child表中的相关条目。

我们在Postgres中有类似“条件CASCADE”的东西吗?或者是手动删除child表中的条目的解决方案吗?

2 个答案:

答案 0 :(得分:1)

您必须在触发器中执行此操作,该触发器将执行ON UPDATE操作。在NEW.state =“被动”的地方,删除子行。

答案 1 :(得分:0)

没有像“条件CASCADE”那样的东西。最让人想到的是disable triggers。但这对你的情况没有帮助。

假设:
- state定义为NOT NULL - parent_id 从不更改。如果是的话,你也想要级联那个UPDATE。

触发触发器ON UPDATE的条件应为:

     NEW.state =  "passive"
AND  OLD.state <> "passive"

..因为你不想一遍又一遍地触发它,只有当父级被设置为“被动”时才会触发它。

CREATE OR REPLACE FUNCTION trg_upbef()
  RETURNS TRIGGER AS
$func$
BEGIN

DELETE FROM child
WHERE  parent_id = OLD.parent_id;  -- OLD works for UPDATE & DELETE

RETURN NEW;
END
$func$ LANGUAGE plpgsql;

而不是checking the condition in the trigger function, you can do that in the trigger directly since Postgres 9.0,从而节省了一些开销:

CREATE TRIGGER upd_cascade_del
BEFORE UPDATE ON parent
FOR EACH ROW
WHEN (NEW.state =  "passive" AND
      OLD.state <> "passive")      -- parenthesis required
EXECUTE PROCEDURE trg_upbef();

不要忘记为ON DELETE添加触发器。您通常不会删除,但如果您这样做,则需要引发异常或级联操作 触发功能必须为RETURN OLD,因为在这种情况下未定义NEW。否则相同:

CREATE OR REPLACE FUNCTION trg_delbef()
...    
RETURN OLD;
...
$func$ LANGUAGE plpgsql;


CREATE TRIGGER del_cascade_del
BEFORE DELETE ON parent
FOR EACH ROW
WHEN (OLD.state <> "passive")      -- only if not already passive
EXECUTE PROCEDURE trg_delbef();