2

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

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

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

4

2 回答 2

1

您必须在执行更新操作的触发器中执行此操作。其中NEW.state="passive",删除子行。

于 2013-08-20T14:07:20.127 回答
0

没有什么像“条件级联”这样的。想到的最接近的事情是禁用触发器。但这对您的情况没有帮助。

假设:
-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();
于 2013-08-20T17:23:30.250 回答