?
このドキュメントでは、 php中國語ネットマニュアル リリース
一個(gè)觸發(fā)器是一種聲明,告訴數(shù)據(jù)庫應(yīng)該在執(zhí)行特定的操作的時(shí)候執(zhí)行特定的函數(shù)。 觸發(fā)器可以定義在一個(gè)INSERT, UPDATE, DELETE命令之前或者之后執(zhí)行,要么是 對每行執(zhí)行一次,要么是對每條 SQL語句執(zhí)行一次。 如果發(fā)生觸發(fā)器事件,那么將在合適的時(shí)刻調(diào)用觸發(fā)器函數(shù)以處理該事件。
觸發(fā)器函數(shù)必須在創(chuàng)建觸發(fā)器之前,作為一個(gè)沒有參數(shù)并且返回trigger類型的函數(shù)定義。 觸發(fā)器函數(shù)通過特殊的TriggerData結(jié)構(gòu)接收其輸入,而不是用普通的函數(shù)參數(shù)方式。
一旦創(chuàng)建了一個(gè)合適的觸發(fā)器函數(shù),就可以用CREATE TRIGGER創(chuàng)建觸發(fā)器。 同一個(gè)觸發(fā)器函數(shù)可以用于多個(gè)觸發(fā)器。
PostgreSQL提供按行與按語句觸發(fā)的觸發(fā)器。按行觸發(fā)的觸發(fā)器函數(shù)為觸發(fā)語句影響的 每一行執(zhí)行一次;按語句觸發(fā)的觸發(fā)器函數(shù)為每條觸發(fā)語句執(zhí)行一次,而不管影響的行數(shù)。 特別是,一個(gè)影響零行的語句將仍然導(dǎo)致按語句觸發(fā)的觸發(fā)器執(zhí)行。 這兩種類型的觸發(fā)器有時(shí)候分別叫做行級觸發(fā)器和語句級觸發(fā)器。
觸發(fā)器還通常分成before觸發(fā)器和after triggers觸發(fā)器。語句級別 的"before"觸發(fā)器通常在語句開始做任何事情之前觸發(fā),而語句級別的"after"觸發(fā)器 在語句結(jié)束時(shí)觸發(fā)。行級別的"before"觸發(fā)器在對特定行進(jìn)行操作之前觸發(fā), 而行級別的"after"觸發(fā)器 在語句結(jié)束的時(shí)候觸發(fā)(但是在任何語句級別的"after"觸發(fā)器之前)。
按語句觸發(fā)的觸發(fā)器應(yīng)該總是返回NULL。 如果必要,按行觸發(fā)的觸發(fā)器函數(shù)可以給調(diào)用它的執(zhí)行者返回一行 數(shù)據(jù)(一個(gè)類型為HeapTuple的數(shù)值), 那些在操作之前觸發(fā)的觸發(fā)器有以下選擇:
它可以返回NULL以忽略對當(dāng)前行的操作。 這就指示執(zhí)行器不要執(zhí)行調(diào)用該觸發(fā)器的行級別操作(對特定行的插入或者更改)。
只用于INSERT和UPDATE行觸發(fā)器: 返回的行將成為被插入的行或者是成為將要更新的行。 這樣就允許觸發(fā)器函數(shù)修改將要被插入或者更新的行。
一個(gè)無意導(dǎo)致任何這類行為的在操作之前觸發(fā)的行級觸發(fā)器必須仔細(xì)返回那個(gè)被 當(dāng)作新行傳進(jìn)來的行。也就是說,對于INSERT 和 UPDATE觸發(fā)器而言, 是NEW行,對于DELETE觸發(fā)器而言,是OLD行。
對于在操作之后觸發(fā)的行級觸發(fā)器,其返回值會被忽略,因此可以返回NULL。
如果多于一個(gè)觸發(fā)器為同樣的事件定義在同樣的關(guān)系上,觸發(fā)器將按照名字的字母順序觸發(fā)。 如果是事件之前觸發(fā)的觸發(fā)器,每個(gè)觸發(fā)器返回的可能已經(jīng)被修改過的行成為下一個(gè) 觸發(fā)器的輸入。如果任何事件之前觸發(fā)的觸發(fā)器返回NULL, 那么對該行的操作將被丟棄并且隨后的觸發(fā)器也不會被觸發(fā)。
一個(gè)觸發(fā)器定義也可以聲明一個(gè)布爾型的WHEN條件,用于檢查觸發(fā)器是否應(yīng)該被觸發(fā)。 在行級別觸發(fā)器上,WHEN條件可以檢查舊和/或新的列值。語句級的觸發(fā)器 也可以有WHEN條件,盡管對其沒有用。在一個(gè)before觸發(fā)器中,WHEN條件 只在函數(shù)正在或?qū)⒈粓?zhí)行之前被觸發(fā)執(zhí)行,因此使用WHEN條件實(shí)際上與在觸發(fā)器開始時(shí) 執(zhí)行相同條件的結(jié)果時(shí)一樣的。然而,在一個(gè)after觸發(fā)器中,WHEN條件只有在發(fā)生更新行時(shí) 才會執(zhí)行,并且決定在語句結(jié)束之后,一個(gè)事件是否需要等待觸發(fā)觸發(fā)器。 因此當(dāng)一個(gè)after觸發(fā)器的WHEN條件沒有返回真時(shí),隊(duì)列中的時(shí)間不需要在 語句結(jié)束后重新讀取行。如果觸發(fā)器只會被幾些行觸發(fā)時(shí),在修改許多行的語句中會明顯提高速度。
通常,行的 before 觸發(fā)器用于檢查或修改將要插入或者更新的數(shù)據(jù)。比如, 一個(gè) before 觸發(fā)器可以用于把當(dāng)前時(shí)間插入一個(gè)timestamp column字段,或者跟蹤該行的 兩個(gè)元素是一致的。行的 after 觸發(fā)器多數(shù)用于填充或者更新其它表,或者對其它表 進(jìn)行一致性檢查。這么區(qū)分工作的原因是 after 觸發(fā)器肯定可以看到該行的最后數(shù)值, 而 before 觸發(fā)器不能;還可能有其它的 before 觸發(fā)器在其后觸發(fā)。如果你沒有具體的 原因定義觸發(fā)器是 before 還是 after , 那么 before 觸發(fā)器的效率高些,因?yàn)椴僮飨嚓P(guān)的信息不必保存到語句的結(jié)尾。
如果一個(gè)觸發(fā)器函數(shù)執(zhí)行 SQL 命令,而這些命令再次觸發(fā)觸發(fā)器,這就是所謂的級聯(lián)觸發(fā)器。 對級聯(lián)觸發(fā)器的級聯(lián)深度沒有明確的限制。有可能出現(xiàn)級聯(lián)觸發(fā)器導(dǎo)致同一個(gè)觸發(fā)器遞歸調(diào)用的情況; 比如,一個(gè)INSERT觸發(fā)器可能執(zhí)行一個(gè)命令,把一個(gè)額外的行插入同一個(gè)表中, 導(dǎo)致INSERT觸發(fā)器再次觸發(fā)。避免這樣無窮遞歸的問題是觸發(fā)器程序員的責(zé)任。
在定義一個(gè)觸發(fā)器的時(shí)候,可以聲明一些參數(shù)。在觸發(fā)器定義中包含參數(shù)的目的是 允許類似需求的不同觸發(fā)器調(diào)用同一個(gè)函數(shù)。比如,可能有一個(gè)通用的觸發(fā)器函數(shù), 接受兩個(gè)字段名字,把當(dāng)前用戶放在第一個(gè),而當(dāng)前時(shí)間戳在第二個(gè)。只要寫得恰當(dāng), 那么這個(gè)觸發(fā)器函數(shù)就可以和觸發(fā)它的特定表無關(guān)。這樣同一個(gè)函數(shù)就可以用于有著合適 字段的任何表的INSERT事件,實(shí)現(xiàn)自動跟蹤交易表中的記錄創(chuàng)建之類的問題。 如果定義成一個(gè)UPDATE觸發(fā)器,還可以用它跟蹤最后更新的事件。
每種支持觸發(fā)器的編程語言都有自己的方法讓觸發(fā)器函數(shù)得到輸入數(shù)據(jù)。 這些輸入數(shù)據(jù)包括觸發(fā)器事件的類型(比如 INSERT 或 UPDATE)以及所有在 CREATE TRIGGER里面列出的參數(shù)。對于低層次的觸發(fā)器,輸入數(shù)據(jù)也包括INSERT 和 UPDATE觸發(fā)器的NEW和/或INSERT和 UPDATE 觸發(fā)器的OLD行。 語句級別的觸發(fā)器目前沒有任何方法檢查該語句修改的獨(dú)立行。