在表中创建触发器。
CREATE [ OR REPLACE ] TRIGGER trigger-name trigger-type { trigger-event-list | UPDATE OF column-list } [ ORDER integer ] ON table-name [ REFERENCING [ OLD AS old-name ] [ NEW AS new-name ] [ REMOTE AS remote-name ] ] [ FOR EACH { ROW | STATEMENT } ] [ WHEN ( search-condition ) ] trigger-body
column-list : column-name[, ...]
trigger-type : BEFORE | AFTER | INSTEAD OF | RESOLVE
trigger-event-list : trigger-event[, ... ]
trigger-event : DELETE | INSERT | UPDATE ( column-name ) | UPDATING [ ( column-name-string ) ]
trigger-body :BEGIN 语句。请参见BEGIN 语句。
触发器事件 触发器可以由以下事件触发。您可以为 DELETE、INSERT 或 UPDATE 事件定义多个触发器,或为 UPDATE OF column-list 事件定义一个触发器:
如果指定 UPDATE 子句,还必须提供一个 REFERENCING 子句以避免出现语法错误。
UPDATE OF column-list 子句 每当更新关联表中的行和修改 column-list 中的列时就被调用。这种类型的触发器事件无法在 trigger-event-list 中使用;它必须是为触发器定义的唯一的触发器事件。此子句不能在 INSTEAD OF 触发器中使用。
您可以为需要处理的每个事件分别编写触发器,如果您有一些共享操作和一些取决于事件的操作,也可以为所有事件创建一个触发器并使用 IF 语句辨别所发生的操作。
UPDATING 子句
UPDATING 的参数是用引号引起的字符串(例如,UPDATING( 'mycolumn' )
)。UPDATE 的参数是一个标识符(例如,UPDATE( mycolumn )
)。两种版本可以互操作,包括这两种版本是为了与其他供应商的 DBMS 的 SQL 方言兼容。
如果指定 UPDATING 子句,还必须提供一个 REFERENCING 子句以避免出现语法错误。
trigger-type 可以将行级触发器定义为在插入、更新或删除操作之前 (BEFORE)、之后 (AFTER) 执行,或替代 (INSTEAD OF) 其中一个操作执行。可以将语句级触发器定义为替代 (INSTEAD OF) 语句执行或在语句之后 (AFTER) 执行。
只要行上发生更新 (UPDATE),BEFORE UPDATE 触发器就会触发,而无论新值是否与旧值不同。也就是说,如果已为 BEFORE UPDATE 触发器指定了 column-list,则 column-list 中的任何列出现在 UPDATE 语句的 SET 子句中都会导致该触发器触发。如果已为 AFTER UPDATE 触发器指定了 column-list,则只有在 column-list 中任意列的值被 UPDATE 语句更改 时触发器才触发。
INSTEAD OF 触发器是可在常规视图上定义的唯一触发器形式。INSTEAD OF 触发器会用其它操作替代触发操作。当 INSTEAD OF 触发器触发时,会跳过触发操作而执行指定的操作。可将 INSTEAD OF 触发器定义为行级或语句级触发器。语句级 INSTEAD OF 触发器会替换整个语句,包括全部行级操作。如果语句级 INSTEAD OF 触发器触发,则该语句不会导致任何行级触发器的触发。但是,语句级触发器的主体可能会执行其它操作,从而导致其它行级触发器的触发。
如果正在定义 INSTEAD OF 触发器,则无法使用 UPDATE OF column-list 子句、ORDER 子句或 WHEN 子句。
RESOLVE 触发器类型可与 SQL Remote 一同使用;它仅在行级 UPDATE 或 UPDATE OF column-list 之前触发。
ORDER 子句 定义同时触发(之前、之后或解析)的相同类型的附加触发器(插入、更新或删除)时,必须指定一个 ORDER 子句来告知数据库服务器触发器触发的顺序。配置为在同时触发的相同类型触发器之间,顺序编号必须是唯一的。如果指定的顺序编号不是唯一的,则会返回错误。顺序编号不需要连续(例如可以指定 1、12、30)。数据库服务器从最低编号开始触发触发器。
如果忽略 ORDER 子句或指定 0,则数据库服务器会指派顺序 1。但是,如果另一相同类型触发器已设置为 1,则会返回错误。
添加附加触发器时,可能需要修改事件的现有相同类型触发器,这取决于触发器的操作是否进行交互。如果它们不进行交互,则新触发器的 ORDER 值必须高于现有触发器。如果它们进行交互,则需要考虑其它触发器,可能需要更改触发器触发的顺序。
ORDER 子句不能在 INSTEAD OF 触发器中使用,因为在表或视图上只能定义每种类型(插入、更新或删除)的一个 INSTEAD OF 触发器。
REFERENCING 子句 REFERENCING OLD 和 REFERENCING NEW 子句允许您引用已插入、已删除或已更新的行。使用此子句时,UPDATE 被视为删除后插入。
INSERT 会使用 REFERENCING NEW 子句,该子句代表已插入的行。但不使用 REFERENCING OLD 子句。
DELETE 会使用 REFERENCING OLD 子句,该子句代表已删除的行。但不使用 REFERENCING NEW 子句。
UPDATE 用到 REFERENCING OLD 子句,代表更新前的行;并用到 REFERENCING NEW 子句,代表更新后的行。
REFERENCING OLD 和 REFERENCING NEW 的含义因时而异,具体取决于触发器是行级还是语句级触发器。对于行级触发器,REFERENCING OLD 子句允许引用更新或删除之前行中的值,REFERENCING NEW 子句允许引用已插入或更新的值。在 BEFORE 和 AFTER 触发器中可以引用 OLD 和 NEW 行。REFERENCING NEW 子句允许在插入或更新操作发生之前在 BEFORE 触发器中修改新行。
对于语句级触发器,REFERENCING OLD 和 REFERENCING NEW 子句引用保存行的新旧值的已声明临时表。
REFERENCING REMOTE 子句适于和 SQL Remote 一同使用。它允许引用 UPDATE 语句的 VERIFY 子句中的值。它只能和 RESOLVE UPDATE 或 RESOLVE UPDATE OF 列列表触发器一同使用。
FOR EACH 子句 要将触发器声明为行级触发器,请使用 FOR EACH ROW 子句。要将触发器声明为语句级触发器,可以使用 FOR EACH STATEMENT 子句或忽略 FOR EACH 子句。为保证清晰,建议在声明语句级触发器时指定 FOR EACH STATEMENT 子句。
WHEN 子句 仅对搜索条件求值结果为 true 的行触发触发器。WHEN 子句仅能用于行级触发器。此子句不能在 INSTEAD OF 触发器中使用。
trigger-body 触发器主体包含触发操作发生时要执行的操作,由一个 BEGIN 子句组成。
可以在 BEGIN 语句中包含触发器操作条件。触发器操作条件将根据导致触发器触发的触发器事件来执行操作。例如,如果触发器定义为针对更新和删除都触发,则可以为这两种情况指定不同的操作。
CREATE TRIGGER 语句创建与数据库中的表关联的触发器,并在数据库中存储触发器。
您不能在实例化视图上定义触发器。如果这样做,将返回 SQLE_INVALID_TRIGGER_MATVIEW 错误。
触发器声明为行级触发器(此情况下,它在每行修改之前或之后执行)或语句级触发器(此情况下,它在整个触发器语句完成后执行)。
CREATE TRIGGER 将对表进行表锁定,这样就需要表的独占使用权。
必须具有 CREATE ANY TRIGGER 或 CREATE ANY OBJECT 系统特权。此外,您必须是触发器所构建于的表的所有者,或者拥有以下其中一种特权:
要在归其他人所有的视图上创建触发器,您必须具有 CREATE ANY TRIGGER 或 CREATE ANY OBJECT 系统特权,且必须具有 ALTER ANY VIEW 或 ALTER ANY OBJECT 系统特权。
自动提交。
SQL/2008 CREATE TRIGGER 是 SQL/2008 标准的可选 SQL 语言功能 T211 "基本触发器功能" 的一部分。ROW 触发器是可选 SQL 语言功能 T212,而 INSTEAD OF 触发器是可选 SQL 语言功能 T213。
SQL Anywhere 触发器的一些功能是服务商扩充。其中包括:
可选的 OR REPLACE 语法。如果替换现有触发器,则忽略创建新触发器实例的授权。
ORDER 子句。在 SQL/2008 中,按触发器创建顺序触发触发器。
RESOLVE 触发器是服务商扩充。
Transact-SQL Adaptive Server Enterprise 不支持 ROW 和 RESOLVE 触发器。虽然 Adaptive Server Enterprise 支持 Transact-SQL INSTEAD OF 触发器,但 SQL Anywhere Transact-SQL 方言不支持此类触发器。Transact-SQL 触发器使用不同的语法进行定义。
此示例将创建一个语句级触发器。首先,按如下 CREATE TABLE 语句所示创建一个表(需要 CREATE TABLE 系统特权):
CREATE TABLE t0 ( id INTEGER NOT NULL, times TIMESTAMP NULL DEFAULT CURRENT TIMESTAMP, remarks TEXT NULL, PRIMARY KEY ( id ) ); |
接下来,为此表创建一个语句级触发器:
CREATE TRIGGER myTrig AFTER INSERT ORDER 4 ON t0 REFERENCING NEW AS new_name FOR EACH STATEMENT BEGIN DECLARE @id1 INTEGER; DECLARE @times1 TIMESTAMP; DECLARE @remarks1 LONG VARCHAR; DECLARE @err_notfound EXCEPTION FOR SQLSTATE VALUE '02000'; //declare a cursor for table new_name DECLARE new1 CURSOR FOR SELECT id, times, remarks FROM new_name; OPEN new1; //Open the cursor, and get the value LoopGetRow: LOOP FETCH NEXT new1 INTO @id1, @times1,@remarks1; IF SQLSTATE = @err_notfound THEN LEAVE LoopGetRow END IF; //print the value or for other use PRINT (@remarks1); END LOOP LoopGetRow; CLOSE new1 END; |
以下示例将替换在上一个示例中创建的 myTrig 触发器。
CREATE OR REPLACE TRIGGER myTrig AFTER INSERT ORDER 4 ON t0 REFERENCING NEW AS new_name FOR EACH STATEMENT BEGIN FOR L1 AS new1 CURSOR FOR SELECT id, times, remarks FROM new_name DO //print the value or for other use PRINT (@remarks1); END FOR; END; |
下一个示例说明如何在 BEFORE UPDATE 触发器中使用 REFERENCING NEW。此示例确保新 Employees 表中的邮政编码均为大写形式。必须具有 GROUPO.Employees 的 SELECT、ALTER 和 UPDATE 特权,才能执行以下语句:
CREATE TRIGGER emp_upper_postal_code BEFORE UPDATE OF PostalCode ON GROUPO.Employees REFERENCING NEW AS new_emp FOR EACH ROW WHEN ( ISNUMERIC( new_emp.PostalCode ) = 0 ) BEGIN -- Ensure postal code is uppercase (employee might be -- in Canada where postal codes contain letters) SET new_emp.PostalCode = UPPER(new_emp.PostalCode) END; UPDATE GROUPO.Employees SET state='ON', PostalCode='n2x 4y7' WHERE EmployeeID=191; SELECT PostalCode FROM GROUPO.Employees WHERE EmployeeID = 191; |
下一个示例说明如何在 BEFORE DELETE 触发器中使用 REFERENCING OLD。此示例可防止从 Employees 表中删除尚未离职的雇员。
CREATE TRIGGER TR_check_delete_employee BEFORE DELETE ON Employees REFERENCING OLD AS current_employee FOR EACH ROW WHEN ( current_employee.Terminate IS NULL ) BEGIN RAISERROR 30001 'You cannot delete an employee who has not been fired'; END; |
下一个示例说明如何在 BEFORE UPDATE 触发器中使用 REFERENCING NEW 和 REFERENCING OLD。此示例可防止降低雇员薪水。
CREATE TRIGGER TR_check_salary_decrease BEFORE UPDATE ON GROUPO.Employees REFERENCING OLD AS before_update NEW AS after_update FOR EACH ROW BEGIN IF after_update.salary < before_update.salary THEN RAISERROR 30002 'You cannot decrease a salary'; END IF; END; |
下一个示例说明如何在 BEFORE INSERT 和 UPDATE 触发器中使用 REFERENCING NEW。以下示例会创建一个触发器,此触发器将在 SalesOrderItems 表中的行插入或更新前触发。
CREATE TRIGGER TR_update_date BEFORE INSERT, UPDATE ON GROUPO.SalesOrderItems REFERENCING NEW AS new_row FOR EACH ROW BEGIN SET new_row.ShipDate = CURRENT TIMESTAMP; END; |
下面的触发器在 Interactive SQL [结果] 窗格的 [消息] 选项卡上显示一条消息,说明哪个操作导致激发触发器。
CREATE TRIGGER tr BEFORE INSERT, UPDATE, DELETE ON sample_table REFERENCING OLD AS t1old FOR EACH ROW BEGIN DECLARE msg varchar(255); SET msg = 'This trigger was fired by an '; IF INSERTING THEN SET msg = msg || 'insert' ELSEIF DELETING THEN set msg = msg || 'delete' ELSEIF UPDATING THEN set msg = msg || 'update' END IF; MESSAGE msg TO CLIENT END; |
![]() |
使用DocCommentXchange讨论此页。
|
版权 © 2013, SAP 股份公司或其关联公司. - SAP Sybase SQL Anywhere 16.0 |