在創建觸發器之前,必須將觸發器函數定義為不帶參數並返回觸發器類型的函數。(觸發器函數通過特殊的TriggerData結構接收輸入,而不是以普通函數參數的形式。)
壹旦創建了適當的觸發器函數,就可以使用CREATE TRIGGER創建觸發器。同壹個觸發器功能可以用於多個觸發器。
PostgreSQL提供了由行觸發的觸發器和由語句觸發的觸發器。在逐行觸發器中,觸發器函數對觸發觸發器的語句所影響的每壹行執行壹次。相比之下,無論受影響的行數是多少,每當執行適當的語句時,都會執行語句觸發的觸發器。特別是,影響零線的語句仍然會導致執行任何適用的語句觸發的觸發器。這兩種類型的觸發器有時分別稱為行級觸發器和語句級觸發器。
觸發器通常也分為前觸發器和後觸發器。語句級的“before”觸發器通常在語句開始執行任何操作之前觸發,而語句級的“after”觸發器則在語句結束時觸發。行級別的“before”觸發器在特定行被操作時立即觸發,而行級別的“after”觸發器在語句結束時觸發(但在任何語句級別的“after”觸發器之前)。
由語句觸發的觸發器應該總是返回NULL。如果需要,由行觸發的觸發器函數可以向調用它的執行者返回壹個數據行表(HeapTuple類型的數值)。在操作之前觸發的那些觸發器有以下選擇:
它可以返回NULL來忽略對當前行的操作。這指示執行器不要執行調用觸發器的行級操作(插入或更改特定行)。
僅用於插入和更新觸發器:返回的行將成為插入的行或要更新的行。這允許觸發器函數修改插入或更新的行。
在操作無意中導致任何此類行為之前觸發的行級觸發器必須小心地返回作為新行傳入的同壹行(即插入和更新觸發器的新行和刪除觸發器的舊行)。
對於在操作後觸發的行級觸發器,它們的返回值被忽略,因此它們可以返回NULL。
如果為同壹事件的同壹關系定義了多個觸發器,則觸發器將按名稱的字母順序觸發。如果觸發器在事件之前被觸發,則每個觸發器返回的可能已被修改的行將成為下壹個觸發器的輸入。如果在任何事件之前觸發的觸發器返回空指針,則將放棄對該行的操作,並且不會觸發後續的觸發器。
通常,行的before觸發器用於檢查或修改要插入或更新的數據。例如,before觸發器可用於將當前時間插入時間戳字段,或者跟蹤該行的兩個元素是否壹致。行的After觸發器主要用於填充或更新其他表,或者檢查其他表的壹致性。這種區分的原因是after觸發器肯定可以看到行的最後壹個值,而before觸發器則不能;可能有其他before觸發器會在稍後觸發。如果您沒有特定的理由來定義觸發器是在之前還是之後,那麽before觸發器更有效,因為與操作相關的信息不必保存到語句的末尾。
如果觸發器函數執行SQL命令,那麽這些命令可能會再次觸發觸發器。這就是所謂的級聯觸發。級聯觸發器的級聯深度沒有明確的限制。級聯觸發器有可能導致同壹觸發器的遞歸調用;例如,插入觸發器可能會執行壹個命令,在同壹表中插入壹個額外的行,從而導致插入觸發器再次觸發。避免這種無限遞歸是觸發器程序員的責任。
在定義觸發器時,我們可以聲明壹些參數。在觸發器定義中包含參數的目的是允許具有相似需求的不同觸發器調用相同的函數。例如,我們可能有壹個通用的觸發器函數,它接受兩個字段名稱,將當前用戶放在第壹個字段中,將當前時間戳放在第二個字段中。只要我們寫得合適,那麽這個觸發函數就可以獨立於觸發它的特定表。這樣,相同的函數可以用於任何具有適當字段的表的插入事件,從而自動跟蹤事務表中記錄的創建。如果定義為更新觸發器,我們也可以用它來跟蹤最後更新的事件。
每種支持觸發器的編程語言都有自己的方法來獲取觸發器函數的輸入數據。這些輸入數據包括觸發事件的類型(例如,插入或更新)以及CREATE TRIGGER中列出的所有參數。對於低級觸發器,輸入數據還包括插入和更新觸發器的新行,和/或更新和刪除觸發器的舊行。語句級觸發器目前無法檢查由change語句修改的獨立行。