我有parent
一个child
表,其中child
有一个 FK 指向父表的 PK。当我删除父表中的某些内容时,我也可以通过删除子记录来删除ON DELETE CASCADE
.
但是,在我的parent
表中,我根本不删除记录。相反,我设置了列state = "passive"
。我想删除表中的相关条目child
。
我们在 Postgres 中有类似“条件级联”的东西吗?还是手动删除表中条目的解决方案child
?
我有parent
一个child
表,其中child
有一个 FK 指向父表的 PK。当我删除父表中的某些内容时,我也可以通过删除子记录来删除ON DELETE CASCADE
.
但是,在我的parent
表中,我根本不删除记录。相反,我设置了列state = "passive"
。我想删除表中的相关条目child
。
我们在 Postgres 中有类似“条件级联”的东西吗?还是手动删除表中条目的解决方案child
?
您必须在执行更新操作的触发器中执行此操作。其中NEW.state="passive",删除子行。
没有什么像“条件级联”这样的。想到的最接近的事情是禁用触发器。但这对您的情况没有帮助。
假设:
-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;
从 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
。您通常不会 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();