2016-09-25 82 views
1

我有下列表格。PostgreSQL多重觸發器和函數

tbl_groups包含所有當前數據,並且當它更改時將名稱存儲在歷史記錄表中。

CREATE TABLE tbl_groups (
    id integer NOT NULL, 
    name varchar NOT NULL, 
    active boolean NOT NULL 
); 

CREATE TABLE tbl_groups_history (
    id integer NOT NULL, 
    group_id integer NOT NULL, 
    name varchar NOT NULL   
); 

當活動字段爲false時,可能不會發生更新。所以,我創建了這個觸發拋出一個異常,當發生這種情況:

CREATE OR REPLACE FUNCTION fn_group_deny_update_when_inactive() RETURNS TRIGGER AS 
$BODY$ 
    BEGIN 
     IF 
      OLD.active = false 
     THEN 
      RAISE EXCEPTION 'Record is inactive'; 
     END IF; 
     RETURN NEW; 
    END; 
$BODY$ 
LANGUAGE plpgsql; 

CREATE TRIGGER 01_group_can_update 
BEFORE UPDATE ON tbl_groups 
FOR EACH ROW 
EXECUTE PROCEDURE fn_group_deny_update_when_inactive(); 

我也有將記錄寫入歷史表

CREATE OR REPLACE FUNCTION fn_group_log_history() RETURNS trigger as 
$BODY$ 
    BEGIN 
     IF 
      (NEW.name <> OLD.name)  
     THEN 
      INSERT INTO tbl_groups_history (group_id, name) 
      VALUES (OLD.id, OLD.name); 
     END IF; 
     RETURN NEW; 
    END; 
$BODY$ 
LANGUAGE plpgsql; 

CREATE TRIGGER 02_group_write_history_log 
BEFORE UPDATE ON tbl_groups 
FOR EACH ROW 
EXECUTE PROCEDURE fn_group_log_history(); 

我曾與01,並命名爲觸發器觸發02作爲前綴,所以我知道它們將按照什麼順序執行,因爲PostgreSQL按字母順序觸發它們。

我對這種做法的一些問題,因爲我不敢肯定,如果這是很好的做法:

  1. 是否有可能有一個之前tbl_groups觸發更新,在一個特定的順序執行這些兩個功能?
  2. 只有一個函數能夠首先檢查「活動」字段,並且如果它繼續,執行歷史記錄,那麼更好嗎?所以我將只有1個(更大的)功能和1個觸發器。

一切都在一個功能:

CREATE OR REPLACE FUNCTION fn_group_before_update() RETURNS trigger as 
$BODY$ 
    BEGIN 
     IF 
      OLD.active = false 
     THEN 
      RAISE EXCEPTION 'Record is inactive'; 
     END IF; 
     IF 
      (NEW.name <> OLD.name)  
     THEN 
      INSERT INTO tbl_groups_history (group_id, name) 
      VALUES (OLD.id, OLD.name); 
     END IF; 
     RETURN NEW; 
    END; 
$BODY$ 

這個考慮性能的任何想法,代碼維護之類的東西?

回答

2

兩個問題。在tbl_groups_history

CREATE TRIGGER trg_01_group_can_update 
BEFORE UPDATE ON tbl_groups 
FOR EACH ROW 
EXECUTE PROCEDURE fn_group_deny_update_when_inactive(); 

接下來,id應該是串行::01_group_can_update是不是一個合適的名字,所以改變這種爲如

CREATE TABLE tbl_groups_history (
    id serial NOT NULL, 
    group_id integer NOT NULL, 
    name varchar NOT NULL   
); 

沒有理由擁有一個以上的觸發你的情況,所以第二種解決方案似乎更好。但是,第一個變體也應該起作用。每the documentation

如果爲同一關係上的同一事件定義了多個觸發器,觸發器將按照觸發器名稱的字母順序觸發。在BEFORE和INSTEAD OF觸發器的情況下,每個觸發器返回的可能修改的行成爲下一個觸發器的輸入。如果任何BEFORE或INSTEAD OF觸發器返回NULL,則對該行放棄該操作,並且不觸發後續觸發器(對於該行)。

+0

有趣的是,如果該觸發器返回NULL,操作將被放棄,我錯過了該部分。因此,如果我有多個觸發器,那麼搜索可能的錯誤將是更多的工作。我有點覺得多重觸發器對於這個目的有點太過分了。而對於觸發器的名字,你是對的,那更好。我還在fn_前面加上了函數的前綴,所以我必須在觸發器上使用trg_ – koala