?
このドキュメントでは、 php中國(guó)語(yǔ)ネットマニュアル リリース
CREATE TRIGGER name { BEFORE | AFTER } { event [ OR ... ] } ON table [ FOR [ EACH ] { ROW | STATEMENT } ] [ WHEN ( condition ) ] EXECUTE PROCEDURE function_name ( arguments )
CREATE TRIGGER創(chuàng)建一個(gè)新的觸發(fā)器。觸發(fā)器將與指定表關(guān)聯(lián)并且將在特定事件發(fā)生時(shí)執(zhí)行聲明的function_name函數(shù)。
觸發(fā)器可以聲明為在對(duì)記錄進(jìn)行操作之前(在檢查約束之前和INSERT,UPDATE,DELETE執(zhí)行前) 或操作完成之后(在檢查約束之后和完成INSERT,UPDATE,DELETE操作)觸發(fā)。如果觸發(fā)器在事件之前, 觸發(fā)器可能略過(guò)當(dāng)前記錄的操作或改變被插入的記錄(只對(duì)INSERT,UPDATE操作有效)。 如果觸發(fā)器在事件之后,所有更改,包括其他觸發(fā)器的影響都是"可見(jiàn)"的。
一個(gè)被標(biāo)記為FOR EACH ROW的觸發(fā)器為操作修改的每一行都調(diào)用一次。比如, 一個(gè)影響10行的DELETE將導(dǎo)致任何在目標(biāo)關(guān)系上的ON DELETE觸發(fā)器獨(dú)立調(diào)用10次, 每個(gè)被刪除的行調(diào)用一次。相比之下,一個(gè)被標(biāo)記為FOR EACH STATEMENT的觸發(fā)器只執(zhí)行一次, 而不管有多少行被修改。特別是,一個(gè)修改零行的操作仍然會(huì)導(dǎo)致合適的FOR EACH STATEMENT觸發(fā)器被執(zhí)行。
另外,定義觸發(fā)器來(lái)啟動(dòng)TRUNCATE,盡管僅僅 FOR EACH STATEMENT。
另外,一個(gè)觸發(fā)器定義可以聲明一個(gè)布爾WHEN條件,這將會(huì) 被測(cè)試來(lái)查看觸發(fā)器是否會(huì)被啟動(dòng)。在行級(jí)的觸發(fā)器中,WHEN 條件可以測(cè)試一行的舊的和/或新的列值。語(yǔ)句級(jí)觸發(fā)器也可以有 WHEN條件,盡管該特性對(duì)他們來(lái)說(shuō)并不是如此有用,因?yàn)? 條件不能引用表中的任何值。
如果多個(gè)同類型的觸發(fā)器為同一事件做了定義,那么它們將按照字母 順序被觸發(fā)。
SELECT并不更改任何行,因此你不能創(chuàng)建 SELECT觸發(fā)器。這種場(chǎng)合下規(guī)則和視圖更合適些。
請(qǐng)參考Chapter 36獲取更多觸發(fā)器信息。
賦予新觸發(fā)器的名稱。它必需和任何作用于同一表的觸發(fā)器不同。
決定該函數(shù)是在事件之前還是之后調(diào)用。
INSERT, UPDATE, DELETE, 或者 TRUNCATE之一; 這制指定了將會(huì)觸發(fā)觸發(fā)器的事件。多個(gè)事件可以通過(guò)使用 OR來(lái)聲明。
對(duì)于UPDATE觸發(fā)器,可以用該語(yǔ)法來(lái)聲明一 系列的列:
UPDATE OF column_name1 [, column_name2 ... ]
觸發(fā)器僅僅在至少有一個(gè)列出的列作為更新的目標(biāo)時(shí)才觸發(fā)。
觸發(fā)器作用的表名稱(可以用模式修飾)。
這些選項(xiàng)聲明觸發(fā)器過(guò)程是否為觸發(fā)器事件影響的每個(gè)行觸發(fā)一次,還是只為每條SQL語(yǔ)句觸發(fā)一次。 如果都沒(méi)有聲明,那么FOR EACH STATEMENT將是缺省。
一個(gè)決定觸發(fā)函數(shù)是否會(huì)真正執(zhí)行的布爾型表達(dá)式。若聲明 WHEN,函數(shù)僅在condition返回true 時(shí)被調(diào)用。在FOR EACH ROW觸發(fā)器中, WHEN條件可以參考舊的和/或新的行值的列,通過(guò)分別寫 OLD.column_name或 NEW.column_name。 當(dāng)然,INSERT觸發(fā)器不能參照OLD 并且DELETE觸發(fā)器不能參照NEW。
當(dāng)前,WHEN表達(dá)式不包括子查詢。
一個(gè)用戶提供的函數(shù),它聲明為不接受參數(shù)并且返回trigger類型,該函數(shù)將在觸發(fā)器被觸發(fā)時(shí)調(diào)用。
一個(gè)可選的用逗號(hào)分隔的參數(shù)列表,它將在觸發(fā)器執(zhí)行的時(shí)候提供給函數(shù)。 這些參數(shù)是文本字符串常量。也可以在這里寫簡(jiǎn)單的名字和數(shù)值常量,但是它們會(huì)被轉(zhuǎn)換成字符串。 請(qǐng)檢查實(shí)現(xiàn)語(yǔ)言中關(guān)于如何在觸發(fā)器函數(shù)中訪問(wèn)觸發(fā)器參數(shù)的描述;這些參數(shù)可能和普通的函數(shù)參數(shù)不同。
要在表上創(chuàng)建一個(gè)觸發(fā)器,用戶必需在該表上有TRIGGER權(quán)限。
使用DROP TRIGGER刪除一個(gè)觸發(fā)器。
一個(gè)特定列觸發(fā)器(FOR UPDATE OF column_name)將會(huì)觸發(fā),當(dāng)其 所有列都像UPDATE命令的SET列表一樣排列。 即使當(dāng)觸發(fā)器未被觸發(fā),列值也是可以更改的,因?yàn)橥ㄟ^(guò) BEFORE UPDATE觸發(fā)器對(duì)行內(nèi)容做的更改不會(huì)考慮。 相反地,像UPDATE ... SET x = x ...這樣的命令會(huì)觸發(fā)一個(gè) 列x上的觸發(fā)器,即使獵德值不改變。
In a BEFORE trigger, the WHEN condition is evaluated just before the function is or would be executed, so using WHEN is not materially different from testing the same condition at the beginning of the trigger function. Note in particular that the NEW row seen by the condition is the current value, as possibly modified by earlier triggers. Also, a BEFORE trigger's WHEN condition is not allowed to examine the system columns of the NEW row (such as oid), because those won't have been set yet. 在一個(gè)BEFORE觸發(fā)器中,WHEN條件盡在函數(shù)被執(zhí)行時(shí) 或之前被評(píng)估,所以使用WHEN本質(zhì)上等同于測(cè)試相同的條件, 在觸發(fā)函數(shù)的開始。特別注意,條件看到的NEW行是當(dāng)前值,可 通過(guò)早先的觸發(fā)器來(lái)調(diào)整。并且,一個(gè)BEFORE觸發(fā)器的 WHEN條件不允許來(lái)測(cè)試 NEW行的系統(tǒng)列(比如 oid)因?yàn)槟切┻€未設(shè)置。
在一個(gè)AFTER觸發(fā)器中,WHEN條件盡在行更新發(fā)生后 評(píng)估,并且決定一個(gè)事件是否會(huì)在語(yǔ)句末排隊(duì)來(lái)觸發(fā)觸發(fā)器。所以當(dāng) AFTER觸發(fā)器的WHEN條件不返回真值, 既沒(méi)必要讓時(shí)間排隊(duì)也沒(méi)必要在語(yǔ)句末重新抓取行。這可以導(dǎo)致在更改多行的 語(yǔ)句中速度顯著提升,若觸發(fā)器僅僅需要為幾行觸發(fā)。
在PostgreSQL7.3以前,必須把觸發(fā)器函數(shù)聲明為返回opaque占位類型, 而不是trigger類型。為了支持加載老的轉(zhuǎn)儲(chǔ)文件,CREATE TRIGGER將接受一個(gè)聲明為返回opaque的函數(shù), 但是它將發(fā)出一條NOTICE并且把函數(shù)聲明的返回類型改成trigger。
每當(dāng)表accounts的一行要被更新時(shí)就執(zhí)行函數(shù)
check_account_update
。
CREATE TRIGGER check_update BEFORE UPDATE ON accounts FOR EACH ROW EXECUTE PROCEDURE check_account_update();
同樣,但是若列balance被指定為 UPDATE命令的一個(gè)目標(biāo),則僅執(zhí)行函數(shù):
CREATE TRIGGER check_update BEFORE UPDATE OF balance ON accounts FOR EACH ROW EXECUTE PROCEDURE check_account_update();
它僅在列balance有實(shí)際上已更改的值時(shí)執(zhí)行函數(shù):
CREATE TRIGGER check_update BEFORE UPDATE ON accounts FOR EACH ROW WHEN (OLD.balance IS DISTINCT FROM NEW.balance) EXECUTE PROCEDURE check_account_update();
調(diào)用一個(gè)函數(shù)來(lái)記錄accounts更新,但僅在以下情況時(shí)更改:
CREATE TRIGGER log_update AFTER UPDATE ON accounts FOR EACH ROW WHEN (OLD.* IS DISTINCT FROM NEW.*) EXECUTE PROCEDURE log_account_update();
Section 36.4包含了一個(gè)用C語(yǔ)言寫的 完整的觸發(fā)器函數(shù)的例子。
PostgreSQL里的 CREATE TRIGGER語(yǔ)句實(shí)現(xiàn)了一個(gè)SQL 標(biāo)準(zhǔn)的子集。目前仍然缺少下面的功能:
SQL 允許你為"old"和"new"行或者表定義別名,用于定義觸發(fā)器的動(dòng)作 (也就是CREATE TRIGGER ... ON tablename REFERENCING OLD ROW AS somename NEW ROW AS othername ...)。 因?yàn)?span id="377j5v51b" class="PRODUCTNAME">PostgreSQL允許觸發(fā)器過(guò)程以任意數(shù)量的用戶定義語(yǔ)言進(jìn)行書寫,所以訪問(wèn)數(shù)據(jù)的工作是用和語(yǔ)言相關(guān)的方法實(shí)現(xiàn)的。
PostgreSQL只允許為觸發(fā)的動(dòng)作執(zhí)行用戶預(yù)先定義好的函數(shù)。SQL標(biāo)準(zhǔn)允許執(zhí)行一些其它的命令, 比如拿CREATE TABLE作為觸發(fā)器動(dòng)作。這個(gè)限止并不難繞開,只要?jiǎng)?chuàng)建一個(gè)執(zhí)行這些命令的用戶預(yù)定的函數(shù)即可。
SQL要求多個(gè)觸發(fā)器應(yīng)該以創(chuàng)建的時(shí)間順序執(zhí)行。 PostgreSQL采用的是按照名字順序, 并認(rèn)為這樣更加方便。
SQL要求必須在級(jí)聯(lián)DELETE完成之后再觸發(fā)級(jí)聯(lián)刪除上的BEFORE DELETE觸發(fā)器。 PostgreSQL的行為是BEFORE DELETE將永遠(yuǎn)在刪除動(dòng)作之前觸發(fā),即使對(duì)于級(jí)聯(lián)刪除也是如此, 我們認(rèn)為這樣更一致。 也有一些不可預(yù)期的情況,當(dāng)BEFORE觸發(fā)器調(diào)整行 或者阻止在由參考動(dòng)作引起的更新時(shí)更新。這會(huì)導(dǎo)致約束違反或者不遵循 引用約束的存儲(chǔ)數(shù)據(jù)。
用OR給一個(gè)觸發(fā)器聲明多個(gè)動(dòng)作是 PostgreSQL對(duì)標(biāo)準(zhǔn)的擴(kuò)展。
為TRUNCATE觸發(fā)觸發(fā)器的能力是SQL標(biāo)準(zhǔn)的一個(gè) PostgreSQL擴(kuò)展。