38.6. PL/Tcl 裡的觸發器過程

觸發器過程可以用 PL/Tcl 寫。PostgreSQL 要求當做觸發器調用的過程必需聲明為沒有參數並且返回類型為 trigger 的函數。

觸發器管理器傳遞給過程體的信息是通過下面變量傳遞的:

$TG_name

CREATE trigger語句裡的觸發器名稱。

$TG_relid

導致觸發器被調用的表的對象標識。

$TG_relatts

以一個空表元素為前導的表中字段名稱的 Tcl 列表。 所以用Tcl命令 lsearch在列表裡查找元素名稱時, 返回的從 1 開始計數的正整數,與PostgreSQL 裡字段編號的傳統一樣。

$TG_when

由觸發器調用事件決定的字符串BEFOREAFTER

$TG_level

由觸發器調用事件決定的字符串ROWSTATEMENT

$TG_op

由觸發器調用事件決定的字符串INSERTUPDATEDELETE

$NEW

一個關聯數組,包含INSERT/UPDATE 動作的新表行,如果是DELETE則為空。 該數組是用字段名做索引的。那些為 NULL 的字段不會在數組中出現!

$OLD

一個關聯數組,包含UPDATE/DELETE 動作的新表行,如果是INSERT則為空。 該數組是用字段名做索引的。那些為 NULL 的字段不會在數組中出現。

$args

如同在CREATE trigger語句裡給出的參數一樣的 Tcl 參數表。 這些參數在過程體裡可以通過$1...$n來訪問。

觸發器過程返回的值是字符串OKSKIP之一, 或者一個象array get Tcl 命令返回的數組那樣的東西。 如果返回值是OK,觸發觸發器的操作 (INSERT/UPDATE/DELETE)將會正常進行。 SKIP告訴觸發器管理器不聲不響地忽略該行的操作。 如果返回一個數組,那麼它告訴 PL/Tcl 返回一個修改後的行給觸發器管理器, 該行將代替在$NEW(只在INSERT/UPDATE 中起作用)中給出的行。 當然,這些只有在觸發器是BEFOREFOR EACH ROW時才有意義;否則返回值將被忽略。

下面是一個小的觸發器過程的例子, 它強制表內的一個整數值對行的更新次數進行跟蹤。 對插入的新行,該值初始化為 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 PROCEDURE trigfunc_modcount('modcnt');

請注意觸發器過程本身並不知道字段名字;那些是從觸發器參數中提供的。這樣就讓我們可以將觸發器過程復用于不同的表。