2017-05-22 70 views
0

我設置了一個函數,當我在tableA中插入時觸發的觸發器,我首先在tableB中創建一個條目,然後在tableC中創建一些其他條目,其中有一個外鍵與tableB相關。但是,我得到一個錯誤,因爲它試圖向tableC插入一個外鍵字段中的一個值,該值不在tableB中存在,只要該函數沒有完成運行。函數PostgreSQL 9.5中的排序結果

有沒有一種方法,在函數內部,在函數內部放置某種返回,但不會退出函數,然後執行其餘部分?一些東西,應該是這樣的:

CREATE OR REPLACE FUNCTION trigger1() RETURNS trigger AS 
$BODY$ 
begin 
insert into tableB values (new.value); 
RETURN NEW; 
insert into tableC (id, fkey) values (new.something, new.value); 
RETURN NEW; 
end; 
$BODY$ 
LANGUAGE plpgsql; 

我試圖函數在兩個不同的觸發器分開,使用字母順序命令執行,但沒有成功,也許是因爲他們都是運行之前...

有什麼想法?

感謝

回答

2

中聲明表C外鍵爲DEFERRABLE INITIALLY DEFERRED

the documentation:

DEFERRABLE不可推遲

該控制約束是否可以被推遲。在每個 命令後立即檢查不可延遲的約束。檢查可推遲的約束可以推遲到 ,直到事務結束(使用SET CONSTRAINTS命令)。 NOT DEFERRABLE是默認值。目前,只有UNIQUE,PRIMARY KEY, EXCLUDE和REFERENCES(外鍵)約束才接受此子句。 NOT NULL和CHECK約束不可延遲。

Btw。函數體中的第一個RETURN NEW;是沒有意義的。

+0

感謝。我很難理解這項工作。如果推遲外鍵並且CONSTRAINT沒有得到尊重,會發生什麼?它會引發錯誤嗎?在交易結束時,它會「記住」整個交易並取消它? –

+1

是的,在約束失敗時會引發錯誤並且事務將回滾。但是,您不必使用明確的事務。如果您沒有外部交易,那麼觸發器功能本身就是單個交易。一般而言,它的工作原理與您所期望的相同,無需更改觸發器中的任何內容。 – klin

2

首先,在同一個函數流中不可能有兩個RETURN語句。

關於你的問題,有很多方法可以做到這一點。其中一個使用DEFERRABLE TRIGGER(在交易結束時評估的特殊類型的觸發器)。喜歡的東西:

--Trigger function 
CREATE OR REPLACE FUNCTION trigger1() RETURNS trigger AS 
$BODY$ 
BEGIN 
    INSERT INTO "tableB" VALUES (new.value); 
    INSERT INTO "tableC" (id, fkey) VALUES (new.something, new.value); 
    RETURN NEW; 
END; 
$BODY$ 
LANGUAGE plpgsql; 

--Trigger raised at end of transaction. Take a look on 'CONSTRAINT' and 'INITIALLY DEFERRED' clauses. 
CREATE CONSTRAINT TRIGGER deferred_trigger_1 
    AFTER INSERT OR UPDATE 
    ON "tableA" 
    INITIALLY DEFERRED 
    FOR EACH ROW 
    EXECUTE PROCEDURE trigger1(); 

更多信息here

+0

謝謝。但是,我無法找到這些可伸縮觸發器如何工作。你能否給我提供這些觸發器語法的例子? –

+0

@GuiOmClair查看我更新的答案。 –