SQLite建立觸發器 CREATE TRIGGER

l_serein發表於2012-11-09

CREATE TRIGGER sql-statement ::=CREATE[TEMP|TEMPORARY]TRIGGERtrigger-name[BEFORE|AFTER]
database-eventON[database-name.]table-name
trigger-actionsql-statement ::=CREATE[TEMP|TEMPORARY]TRIGGERtrigger-nameINSTEAD OF
database-eventON[database-name.]view-name
trigger-actiondatabase-event ::=DELETE|
INSERT
|
UPDATE
|
UPDATE OF
column-listtrigger-action ::=[FOR EACH ROW|FOR EACH STATEMENT][WHENexpression]
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處可用,例如:

INSERTNEW可用UPDATENEW和OLD均可用DELETEOLD可用

當使用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語句 不會出錯,而會觸發關聯的觸發器。檢視關聯的表不會被修改。(除了由觸發器進行的修改操作)。

Example:

假設"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刪除觸發器

相關文章