2013-08-20 2 views
2

parentchild 표가 있습니다. 여기에서 child은 상위 표의 PK를 가리키는 FK입니다. 부모 테이블에서 무언가를 삭제할 때 ON DELETE CASCADE을 가짐으로써 하위 레코드를 삭제할 수 있습니다.외래 키 제약 조건에 대한 조건부 CASCADE 연산?

그러나 내 parent 테이블에서 나는 레코드를 전혀 삭제하지 않습니다. 대신 나는 열 state = "passive"을 설정했습니다. child 테이블에서 관련 항목을 삭제하고 싶습니다.

우리는 Postgres에서 "조건부 캐스케이드"와 같은 것을 가지고 있습니까? 또는 child 테이블의 항목을 수동으로 삭제하는 솔루션입니까?

답변

1

업데이트를 수행하는 트리거에서이 작업을 수행해야합니다. NEW.state = "passive"인 경우, 하위 행을 삭제하십시오.

+0

글쎄, 그래, 우리는 Postgres 또는 그 문제에 대한 조건부 캐스케이드 같은 것이 있는지 궁금 해서요. 어쨌든, 귀하의 회신에 감사드립니다. 감사합니다! – Kaunteya

+0

죄송합니다. PostgreSQL에있는 동물은 없습니다. –

0

"조건부 캐스케이드"와 같은 것은 없습니다. 마음에 가장 가까운 것은 disable triggers입니다. 하지만 그건 네 도움이되지 않아.

가정 :
-stateNOT NULL을 정의한다.
- parent_id이 변경됩니다. 만약 그렇다면 업데이트를 캐스케이드하기를 원할 것입니다.

조건

는해야 트리거 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();