操作的上下文(即它是級聯刪除還是簡單刪除)應該存儲在某個地方。 您可以爲此使用自定義參數。 當級聯(從表tbl1
)進行,觸發器按以下順序發射刪除:
trigger before delete on tbl1
trigger before delete on tbl2
trigger after delete on tbl1
trigger after delete on tbl2
你因此需要兩個觸發器(前,後刪除)上表tbl1
和扳機上表tbl2
之前刪除。
在tbl1
上創建兩個觸發器。在觸發前的功能自定義參數設置爲on
和off
在後觸發功能:
create or replace function tbl1_trigger_before_delete()
returns trigger language plpgsql as $$
begin
set tbl1.cascade to on;
return old;
end $$;
create or replace function tbl1_trigger_after_delete()
returns trigger language plpgsql as $$
begin
set tbl1.cascade to off;
return null;
end $$;
create trigger tbl1_trigger_before_delete
before delete on tbl1
for each row execute procedure tbl1_trigger_before_delete();
create trigger tbl1_trigger_after_delete
after delete on tbl1
for each row execute procedure tbl1_trigger_after_delete();
在tbl2
觸發功能檢查參數的當前值。
create or replace function tbl2_trigger_before_delete()
returns trigger language plpgsql as $$
begin
begin
if current_setting('tbl1.cascade') = 'on' then
raise notice 'cascaded';
else
raise exception '';
end if;
exception when others then
raise notice 'not cascaded';
end;
return old;
end $$;
create trigger tbl2_trigger_before_delete
before delete on tbl2
for each row execute procedure tbl2_trigger_before_delete();
測試::
insert into tbl1 values
(1, '1'),
(2, '2');
insert into tbl2 values
(1, 1, '1'),
(2, 1, '2'),
(3, 2, '3'),
(4, 2, '4');
delete from tbl1 where id = 1;
NOTICE: cascaded
NOTICE: cascaded
DELETE 1
delete from tbl2 where owner = 2;
NOTICE: not cascaded
NOTICE: not cascaded
DELETE 2
替代溶液中的情況下該參數具有尚未設置 異常塊是必要的。
當扳機上表tbl2
之前刪除在級聯刪除,診斷值PG_EXCEPTION_CONTEXT被設置爲一些串的上下文中執行,它是空的時候刪除不級聯:
create or replace function tbl2_trigger_before_delete()
returns trigger language plpgsql as $$
declare
context text;
begin
begin
raise exception '';
exception when others then
GET STACKED DIAGNOSTICS context := PG_EXCEPTION_CONTEXT;
end;
if context = '' then
raise notice 'not cascaded';
else
raise notice 'cascaded';
end if;
return old;
end $$;
create trigger tbl2_trigger_before_delete
before delete on tbl2
for each row execute procedure tbl2_trigger_before_delete();
將該溶液從這個意義上說,它可能是有問題的,它只能從測試中獲得,這種行爲在任何地方都沒有記錄。
嗨克林,第一解決方案是「有效的」,但並不完全符合我的要求。也許我還不夠清楚,但在我寫的賞金評論中,我知道如何解決它(使用多個觸發器),但我想知道Postgresql是否提供這種信息(引用),而不是我可以將信息存儲在某處供以後使用。對於您的信息,第二次嘗試(使用'PG_EXCEPTION_CONTEXT')在運行Postgres 9.4的MacOSX上不起作用,也許這是您注意到的未記錄行爲的副作用。 – Ciaccia
我明白了。其實,我錯過了你的額外評論。至於第二種選擇,我也在Postgres 9.4中測試了這個解決方案。你確定你在**刪除之前測試了一個觸發器**嗎? (刪除後的觸發不能以這種方式工作)。 – klin
您好@klin,我的壞,我在**之前使用了** **而不是** **之前。我可以在不使用異常技巧的情況下區分這兩種情況,只需使用'GET DIAGNOSTICS stack = PG_CONTEXT'。正如我在我原來的問題中寫的,我最初嘗試這種方式,但沒有出現(實際上是因爲之後/之前觸發)。這是非常糟糕的,因爲在PG_CONTEXT只在**觸發器之前工作的任何地方都沒有記錄。此外,這並不完全幫助我,因爲在**之前**觸發器,我仍然不確定該行是否真的被刪除。 – Ciaccia