支援的版本:目前版本 (17) / 16 / 15 / 14 / 13
開發版本:devel
不支援的版本:12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4

42.6. PL/Tcl 中的觸發函數 #

觸發函數可以使用 PL/Tcl 編寫。PostgreSQL 要求作為觸發呼叫的函數必須宣告為不帶參數且傳回類型為 trigger 的函數。

觸發管理器的資訊會透過以下變數傳遞至函數主體

$TG_name

來自 CREATE TRIGGER 陳述式的觸發名稱。

$TG_relid

導致觸發函數被呼叫的表格的物件 ID。

$TG_table_name

導致觸發函數被呼叫的表格名稱。

$TG_table_schema

導致觸發函數被呼叫的表格的綱要。

$TG_relatts

表格欄位名稱的 Tcl 清單,以空白清單元素作為前綴。因此,使用 Tcllsearch 命令在清單中查詢欄位名稱會傳回元素的編號,從第一個欄位開始編號為 1,與 PostgreSQL 中慣用方式相同。(空白清單元素也會出現在已刪除欄位的位置,以便屬性編號對於其右側的欄位是正確的。)

$TG_when

字串 BEFOREAFTERINSTEAD OF,取決於觸發事件的類型。

$TG_level

字串 ROWSTATEMENT,取決於觸發事件的類型。

$TG_op

字串 INSERTUPDATEDELETETRUNCATE,取決於觸發事件的類型。

$NEW

一個關聯陣列,包含 INSERTUPDATE 動作的新表格列的值,對於 DELETE 則為空。該陣列以欄位名稱作為索引。空值欄位不會出現在陣列中。這不適用於陳述式層級觸發。

$OLD

一個關聯陣列,包含 UPDATEDELETE 動作的舊表格列的值,對於 INSERT 則為空。該陣列以欄位名稱作為索引。空值欄位不會出現在陣列中。這不適用於陳述式層級觸發。

$args

一個 Tcl 清單,包含 CREATE TRIGGER 陳述式中給定的函數引數。這些引數也可以在函數主體中作為 $1 ... $n 存取。

觸發函數的回傳值可以是字串 OKSKIP,或是一個欄位名稱/數值配對的列表。如果回傳值是 OK,觸發觸發器的操作(INSERT/UPDATE/DELETE)會照常進行。SKIP 會告訴觸發器管理器靜默地抑制此列的操作。如果回傳一個列表,它會告訴 PL/Tcl 將修改後的列回傳給觸發器管理器;修改後的列的內容由列表中的欄位名稱和數值指定。列表中沒有提到的任何欄位都會設定為 null。回傳修改後的列只對 row-level BEFORE INSERTUPDATE 觸發器有意義,修改後的列將被插入,而不是 $NEW 中給出的列;或對 row-level INSTEAD OF INSERTUPDATE 觸發器有意義,其中回傳的列被用作 INSERT RETURNINGUPDATE RETURNING 子句的來源資料。在 row-level BEFORE DELETEINSTEAD OF DELETE 觸發器中,回傳修改後的列具有與回傳 OK 相同的效果,也就是操作會繼續進行。對於所有其他類型的觸發器,觸發器的回傳值會被忽略。

提示

結果列表可以使用 Tcl 指令 array get 從修改後的元組的陣列表示中建立。

這是一個小的觸發函數範例,它強制表格中的一個整數值來追蹤對列執行的更新次數。對於插入的新列,該值初始化為 0,然後在每次更新操作時遞增。

CREATE FUNCTION trigfunc_modcount() RETURNS trigger AS $$
    switch $TG_op {
        INSERT {
            set NEW($1) 0
        }
        UPDATE {
            set NEW($1) $OLD($1)
            incr NEW($1)
        }
        default {
            return OK
        }
    }
    return [array get NEW]
$$ LANGUAGE pltcl;

CREATE TABLE mytab (num integer, description text, modcnt integer);

CREATE TRIGGER trig_mytab_modcount BEFORE INSERT OR UPDATE ON mytab
    FOR EACH ROW EXECUTE FUNCTION trigfunc_modcount('modcnt');

請注意,觸發函數本身不知道欄位名稱;那是從觸發器引數提供的。這使得觸發函數可以與不同的表格重複使用。

提交更正

如果您在文件中看到任何不正確、與特定功能的經驗不符或需要進一步澄清的內容,請使用此表單來報告文件問題。