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

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

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

$TG_name

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

$TG_relid

導致觸發器被調用的資料表的對象 ID。

$TG_relatts

以一個空資料表元素為前導的資料表中字串名稱的 Tcl 列資料表。 所以用Tcl命令 lsearch在列資料表裡查找元素名稱時, 返回的從 1 開始計數的正整數,與PostgreSQL 裡字串編號的傳統一樣。 (已經被刪除掉的字串位置的空的列資料表元素仍然會出現,這樣,屬性編號與字串的對應就是正確的。)

$TG_when

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

$TG_level

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

$TG_op

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

$NEW

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

$OLD

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

$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');

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