我有parent
和child
表,其中child
有一个FK指向父表的PK。当我删除父表中的某些内容时,我可以通过ON DELETE CASCADE
删除子记录。
但是,在我的parent
表中,我根本不删除记录。相反,我设置了列state = "passive"
。我想删除child
表中的相关条目。
我们在Postgres中有类似“条件CASCADE”的东西吗?或者是手动删除child
表中的条目的解决方案吗?
答案 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();