CREATE TRIGGER
sql-statement ::= | CREATE [TEMP | TEMPORARY] TRIGGER trigger-name [ BEFORE | AFTER ] database-event ON [database-name .] table-name trigger-action |
sql-statement ::= | CREATE [TEMP | TEMPORARY] TRIGGER trigger-name INSTEAD
OF database-event ON [database-name .] view-name trigger-action |
database-event ::= | DELETE | INSERT | UPDATE | UPDATE OF column-list |
trigger-action ::= | [ FOR EACH ROW | FOR
EACH STATEMENT ] [ WHEN expression ] BEGIN trigger-step ; [ trigger-step ; ]* END |
trigger-step ::= | update-statement | insert-statement | delete-statement | select-statement |
CREATE TRIGGER語句用於向數據庫schema中添加觸發器。觸發器是一些在特定的數據庫事件(database-event)發生時自動進行的數據庫操作(trigger-action)。
觸發器可由在特殊表上執行的DELETE、INSERT、UPDATE等語句觸發,或UPDATE表中特定的字段時觸發。
現在SQLite僅支持FOR EACH ROW觸發器,不支持FOR EACH STATEMENT觸發。因此可以不用明確說明FOR EACH ROW。FOR EACH ROW的意思是由trigger-steps說明的SQL語句可能在(由WHEN子句決定的)數據庫插入,更改或刪除的每一行觸發trigger。
WHEN子句和trigger-steps可以使用“NEW.column-name”和“OLD.column-name”的引用形式訪問正在被插入,更改或刪除的行的元素,column-name是觸發器關聯的表中的字段名。OLD和NEW引用只在觸發器與之相關的trigger-event處可用,例如:
INSERT | NEW可用 |
UPDATE | NEW和OLD均可用 |
DELETE | OLD可用 |
當使用WHEN子句,trigger-steps只在WHEN子句爲真的行執行。不使用WHEN時則在所有行執行。
trigger-time決定了trigger-steps執行的時間,它是相對於關聯行的插入、刪除和修改而言的。
作爲的一部分trigger-step的UPDATE或INSERT可以使用ON CONFLICT子句。但若觸發trigger的語句使用了ON CONFLICT子句,則覆蓋前述的ON CONFLICT子句所定義的衝突處理方法。
關聯表被撤銷時觸發器被自動刪除。
不僅在表上,在視圖上一樣可以創建觸發器,在CREATE TRIGGER語句中使用INSTEAD OF即可。若視圖上定義了一個或多個ON INSERT、ON DELETE、ON UPDATE觸發器,則相應地對視圖執行INSERT、DELETE或UPDATE語句不會出錯,而會觸發關聯的觸發器。視圖關聯的表不會被修改。(除了由觸發器進行的修改操作)。
例子:
假設“customers”表存儲了客戶信息,“orders”表存儲了訂單信息,下面的觸發器確保當用戶改變地址時所有的關聯訂單地址均進行相應改變:
CREATE TRIGGER update_customer_address UPDATE OF address ON customers BEGIN UPDATE orders SET address = new.address WHERE customer_name = old.name; END;
定義了該觸發器後執行如下語句:
UPDATE customers SET address = ’1 Main St.’ WHERE name = ’Jack Jones’;
會使下面的語句自動執行:
UPDATE orders SET address = ’1 Main St.’ WHERE customer_name = ’Jack Jones’;
注意,目前在有INTEGER PRIMARY KEY域的表上觸發器可能工作不正常。若BEFORE觸發器修改了一行的INTEGER PRIMARY KEY域,而該域將由觸發該觸發器的語句進行修改,則可能根本不會修改該域。可以用PRIMARY KEY字段代替INTEGER PRIMARY KEY字段來解決上述問題。
一個特殊的SQL函數RAISE()可用於觸發器程序,使用如下語法:
raise-function ::= | RAISE ( ABORT, error-message ) | RAISE ( FAIL, error-message ) | RAISE ( ROLLBACK, error-message ) | RAISE ( IGNORE ) |
當觸發器程序執行中調用了上述前三個之一的形式時,則執行指定的ON CONFLICT進程(ABORT、FAIL或者ROLLBACK)且終止當前查詢,返回一個SQLITE_CONSTRAINT錯誤並說明錯誤信息。
當調用RAISE(IGNORE),當前觸發器程序的餘下部分,觸發該觸發器的語句和任何之後的觸發器程序被忽略並且不恢復對數據庫的已有改變。若觸發觸發器的語句是一個觸發器程序本身的一部分,則原觸發器程序從下一步起繼續執行。
使用DROP TRIGGER刪除觸發器。