CREATE TRIGGER 语句(基本触发器)
CREATE TRIGGER(基本)语句在模式中定义一个基本触发器,并在当前服务器上构建一个触发器包。 每次触发器被激活时,触发器组件都会执行一次或多次。
调用CREATE TRIGGER(基本)
该语句可以嵌入应用程序中,也可以交互式地发出。 这是一个可执行语句,只有在DYNAMICRULES RUN行为生效时才能动态准备。 更多信息,请参阅授权ID和动态SQL。
CREATE TRIGGER(基本)授权
以下定义的特权套装必须至少包含以下一项:
- 模式中的CREATEIN特权
- SYSADM 或 SYSCTRL 权限
- 系统 DBADM
安装 SYSOPR 权限(当前进程的 SQLID 设置为 SYSINSTL 时)
在定义表中的触发器时,下面定义的权限集必须包含 SYSADM 权限或以下各项权限:
- 如果触发器定义中包含引用子句,则触发器定义所在表的SELECT权限
- 触发操作 搜索条件中任何表或视图的 SELECT 权限
- 在触发操作中调用已触发的SQL语句所需的权限
- 授权在表格上定义触发条件,其中必须至少包含以下一项:
- 触发器特权,定义触发器的桌子
- 触发器定义的表格上的ALTER权限
- DBADM 数据库中包含表格的权限
- SYSCTRL 权限
安装 SYSOPR 权限(当前进程的 SQLID 设置为 SYSINSTL 时)
- 系统 DBADM 权限
在定义视图触发器时,下面定义的特权集必须包含 SYSADM 权限或以下各项中的每一项:
如果触发器定义中包含引用子句,则触发器定义视图的 SELECT 权限
- 触发操作 搜索条件中任何表或视图的 SELECT 权限
- 在触发操作中调用已触发的SQL语句所需的权限
- 在视图中定义触发器的授权,其中必须至少包含以下一项:
- 触发定义的观点的所有权
- SYSCTRL 权限
- 系统 DBADM 权限
权限设置:
如果语句嵌入到应用程序中,权限集就是计划或软件包所有者所拥有的权限。 如果所有者是一个角色,则隐式模式匹配不适用,该角色需要包含前面列出的条件之一。
如果语句动态生成,且未在指定了 ROLE AS OBJECT OWNER 子句的可信环境中运行,则权限集是指进程的 SQL 授权 ID 所拥有的权限集。 指定的触发器名称可以包含模式名称(限定符)。 如果架构名称与进程的SQL授权ID不同,则必须满足以下条件之一:
- 特权集包括SYSADM或SYSCTRL权限。
- 该进程的SQL授权ID对模式具有CREATEIN权限。
- SECADM 权限
- CREATE_SECURE_OBJECT权限

CREATE TRIGGER语法(基本)
触发器定义
扳机启动时间
触发器事件
粒度
触发动作
SQL触发器主体
触发SQL语句:
选项列表:

CREATE TRIGGER(基本)描述
- 触发器名称
命名触发器。 名称(包括隐式或显式模式名称)不得标识当前服务器上存在的触发器。 
该名称也用于创建触发包;因此,该名称也不得标识目录中已描述的包。 模式名称将成为触发器包的集合ID。 虽然触发名称可以指定为普通或分隔标识符,但名称应符合普通标识符的规则。 有关更多信息,请参阅隐式创建的触发器软件包。
如果权限集包含 SYSCTRL 权限,模式名称可以是 "SYSTOOLS"。 否则,除非模式名称为 "SYSADM"、"SYSIBMADM "或 "SYSPROC",否则模式名称不得以 "SYS "开头。
之前没有级联
指定触发器为前置触发器。 Db2 在执行触发操作之前,先应用对目标表进行的插入、删除或更新操作所导致的任何更改。 它还规定,触发操作不会激活其他触发器,因为前一个触发器的触发操作不能包含任何更新、REFRESH TABLE或TRUNCATE SQL语句。当 view-name 也被指定时,不能指定BEFORE。 对于触发器“之前”,必须为每一行指定“FOR EACH ROW”。

- AFTER
- 指定触发器为后触发器。 Db2 在执行触发操作后,对目标表进行插入、删除或更新操作,并应用由此产生的任何更改。 如果同时指定了视图名称 ,则无需指定AFTER。
- INSTEAD OF
- 指定触发器为,而不是触发器。 关联的触发操作将替换对主体视图的操作。 在给定的主题视图中,每种操作类型只允许使用一个“代替”触发器。 Db2 执行触发操作 ,而不是在主题视图中执行插入、更新或删除操作。
当同时指定表名时,无需指定“INSTEAD OF”。 INSTEAD OF触发器不能指定WHEN子句。 对于每个语句,不能指定一个代替触发器。
在视图定义中,fullselect 最外层 SELECT 列表中的非数字列必须使用相同的编码方案。
- ON 表名
- 标识触发器定义的“之前”或“之后”的受试者表。 名称必须标识当前服务器上存在的一个基本表。
它不得标识物化查询表、克隆表、临时表、辅助表、别名、同义词、实时统计表、仅加速器表、目录表或目录表。
- ON 视图名称
- 标识触发器定义的“代替”主题视图。 名称必须标识当前服务器上存在的视图。
视图名称不得指定满足以下任何条件的视图:
- 使用“带级联检查”选项(对称视图)定义视图
- 定义对称视图的视图
- 视图引用了使用不同编码方案或CCSID值编码的数据
- 视图有一个ROWID列
- 视图中的列基于以下任何类型的底层列:
- LOB、XML或ROWID列
- 标识列
- 安全标号列
- “行更改时间戳记”列
- “行开始”列
- “行结束”列
- 交易开始ID列
- 视图中有列,列中有字段操作
- 视图的所有基础表都是目录表
- 视图的所有基础表均为全局临时表
- 视图的所有基础表都是克隆表
- 观点取决于其他观点
- REFERENCING
- 指定转换变量的相关名称和转换表的表名。 对于由触发SQL操作(插入、删除或更新)修改的主题表中的行,关联名称用于标识特定行的列。 表标识符用于标识受影响行的完整集合。 在触发器内部无法引用XML类型的转换变量。 如果引用了转换表的列,则该列的数据类型不能是XML。
通过使用以下指定的相关名称限定列名,触发 SQL 操作影响的每一行都可用于触发操作:
OLD AS correlation-name
指定相关性名称,该名称用于识别触发 SQL 操作前记录中的值。
NEW AS correlation-name
指定相关性名称,该名称用于标识被触发 SQL 操作和已执行的 before 触发器中的任何赋值语句修改的记录中的值。
触发操作所影响的一组完整行可通过使用如下指定的表标识符提供给触发操作:
- OLD_TABLE AS 表标识符
- 指定临时表的名称,该临时表用于标识在触发SQL操作之前,实际更改之前,完整行集中被修改的行的值。
NEW_TABLE AS 表标识符
指定临时表的名称,该临时表用于标识被触发 SQL 操作和已执行的 before 触发器中的任何赋值语句修改的整套记录中的值。 
一个触发器只能指定一个 OLD 相关名和一个 NEW 相关名。 一个触发器只能指定一个OLD_TABLE和一个NEW_TABLE 表标识符。 所有相关名称和表格标识符必须相互唯一。
表 1 概述了可为各种触发类型指定的过渡变量和过渡表的允许组合。 仅当触发事件是删除操作或更新操作时,OLD 关联名 和OLD_TABLE表标识符才有效。 对于删除操作,OLD 关联名称捕获已删除行中列的值,OLD_ TABLE表标识符捕获已删除行集中的值。 对于更新操作,OLD 关联名称捕获更新操作前一行各列的值,OLD_T ABLE表标识符捕获更新行集中的值。
只有当触发事件是插入操作或更新操作时,NEW 相关名称和 NEW_TABLE 表标识符才有效。 对于这两种操作, 新的关联名称捕获插入或更新行中列的值,而新的表标识符捕获插入或更新行集中的值。 对于 BEFORE 触发器,更新行的值包括 BEFORE 触发器触发操作中任何赋值语句的更改。
表 1. 触发器定义中允许的属性组合 详细程度 激活时间 触发 SQL 操作 (triggering SQL operation) 允许过渡变量 1 允许使用转换表1 FOR EACH ROW BEFORE 删除 旧 NONE INSERT 新建 NONE UPDATE 旧,新 NONE AFTER 删除 旧 OLD_TABLE INSERT 新建 NEW_TABLE UPDATE 旧,新 旧表,新表 INSTEAD OF 删除 旧 OLD_TABLE INSERT 新建 NEW_TABLE UPDATE 旧,新 旧表,新表 FOR EACH STATEMENT AFTER 删除 NONE OLD_TABLE INSERT NONE NEW_TABLE UPDATE NONE 旧表,新表 注:- 如果引用了不允许引用的转换表或变量,则返回错误。
具有字符数据类型的过渡变量继承主表列的子类型和CCSID。 在触发动作执行期间,过渡变量被视为宿主变量。 因此,可能会发生字符转换。 然而,与宿主变量不同,转换变量可以具有位数据属性,并且位数据永远不会发生字符转换。 如果表中的对应列是位数据,则过渡变量被视为位数据。
您不能修改转换表;转换表是只读的。 虽然转换表不会从主题表中继承任何编辑或验证程序, 但它会继承主题表的编码方案和字段程序。
每个关联名称和每个表标识符的范围是整个触发器定义。
- 粒度
- 每行或每句话
- 指定 Db2 执行触发操作的条件。
- FOR EACH ROW
- 指定 Db2 对触发SQL操作修改的表中的每一行执行触发操作。 如果触发的SQL操作没有修改任何行,则不会执行触发操作。
- FOR EACH STATEMENT
- 指定 Db2 仅对触发操作执行一次触发操作。 即使触发操作不修改或删除任何行,触发操作也会被执行一次。
对于每个语句,不得指定“之前”或“代替”触发器。
- MODE DB2SQL
表示要创建基本触发器。
- NOT SECURED 或 SECURED
- 指定触发器是否视为安全触发器。 默认设置是“未锁定”。
- SECURED
- 指定触发器被视为安全触发器。
如果触发器的目标表使用行访问控制或列访问控制,则必须指定SECURED。 如果为视图创建的触发器,且视图定义中一个或多个基础表使用行访问控制或列访问控制,则必须指定SECURED。
- NOT SECURED
- 指定触发器被认为不安全。
对于使用行访问控制或列访问控制的触发器,不能指定NOT SECURED。 如果视图定义中有一个或多个基础表使用行访问控制或列访问控制,则不能为视图创建的触发器指定NOT SECURED。
- 触发器事件
- 指定当触发事件应用于主体表或视图时,与触发器关联的触发操作将被执行。
- INSERT
- 指定触发器为插入触发器。 Db2 每当在目标表上进行插入操作时,就会执行触发操作。 但是,如果在任何解释表中定义了插入触发器,并且插入操作是由 Db2 向表中添加一行引起的,则不会执行触发操作。
- 删除
- 指定触发器为删除触发器。 Db2 每当对目标表进行删除操作时,就会执行触发操作。
- UPDATE
- 指定触发器为更新触发器。 Db2 每当主题表有更新操作时,就会执行触发操作。
如果您没有指定列名列表,则对目标表任何列(包括随后通过ALTER TABLE语句添加的列)进行的更新操作都会激活触发操作。
- 列名 ,..
- 您指定的每个列名必须是主题表的列,且在列表中只能出现一次。 对列出的任何一列进行更新操作,即可激活触发操作。
UPDATE OF 列名不能指定为INSTEAD OF触发器。
- 触发动作
- 指定触发器激活时执行的操作。 触发操作由一个或多个SQL语句和一个可选条件组成,该条件用于控制语句是否被执行。
- WHEN (搜索条件 )
- 指定一个条件,其值为真、假或未知。 只有当搜索条件为真时,才会执行触发的SQL语句。 如果省略了WHEN子句,则始终执行关联的SQL语句。
INSTEAD OF触发器不能指定WHEN子句。
- SQL触发器主体
指定触发操作要执行的 SQL 语句。 SQL-trigger-body 中只能指定某些 SQL 语句。
- 触发的 SQL 语句
- 指定可在触发器主体中作为唯一语句的SQL语句。
- BEGIN ATOMIC triggered-SQL-statement,.. 结束
- 指定触发操作要执行的SQL语句列表。 这些语句按照指定的顺序执行。
在 SQL触发器主体中只能指定某些SQL语句。
表 2. 允许的SQL语句 SQL 语句 触发器激活时间 BEFORE AFTER INSTEAD OF CALL X X X 删除(已搜索) X X 全查询 X X X INSERT X X MERGE X X REFRESH TABLE X X SET 过渡变量 X 信号 X X X TRUNCATE X X 更新(已搜索) X X 值 X X X VALUES INTO X 触发动作中的语句具有以下限制:- 它们不能引用宿主变量、参数标记、未定义的过渡变量或已声明的临时表。
- 它们只能引用当前服务器上的表或视图。
- 他们只能调用当前服务器上存储的程序或用户定义的函数。 但是,调用的例程可以访问当前服务器以外的其他服务器。
- 如果触发条件定义为“之前”,则不能包含指向主题表的完整选择。
- 他们不能修改属于BUSINESS_TIME时段的列。
- 如果触发条件是先于触发条件:
- 触发器主体中不得包含 DELETE、INSERT、MERGE、REFRESH TABLE、TRUNCATE、UPDATE 语句或 SELECT FROM 数据更改语句 ,也不得引用定义为 MODIFIES SQL DATA 的过程或函数。
- 触发器主体不得直接或间接对包含以下语句之一的程序发出CALL语句:
- ALTER
- COMMENT
- 创建
- 删除
- DROP
- EXCHANGE
- GRANT
- 标签
- LOCK TABLE
- MERGE
- REFRESH TABLE
- RENAME
- REVOKE
- TRUNCATE
- UPDATE
CREATE TRIGGER 语句不能包含十六进制图形字符串(GX)常量。
触发的操作可以参考受影响行集中的值。 通过使用过渡变量和过渡表来支持这一操作。
当定义触发器的版本时, 触发器中引用的所有表、视图、别名、序列、角色、用户定义的数据类型、用户定义的函数和过程必须在当前服务器上存在。 定义触发器版本时,别名所指向的表格或视图也必须存在。
WRAPPED obfuscated-statement-text
FL 500指定触发器的编码定义。 CREATE TRIGGER 语句可以使用 WRAP 标量函数进行编码。WRAPPED 不能在静态 CREATE 语句中指定。

CREATE TRIGGER(基本)的注意事项
- 车主特权:
- 当定义了“代替”触发器时,相关权限(视图上的插入、更新或删除)将赋予视图的所有者。 车主有权将此特权授予他人。 有关对象所有权的更多信息,请参阅授权、特权、权限、掩码和对象所有权。
- 执行授权:
- 执行触发SQL操作的用户无需权限即可执行 SQL触发器主体。 SQL触发器主体使用触发器所有者的权限执行。
- 启动触发器:
- 只有插入、删除或更新操作才能激活触发器。 触发器的激活可能会导致触发器级联。触发器级联是指一个触发器激活后执行SQL语句,从而导致其他触发器或同一触发器再次激活。 触发的操作也可能因原始修改而引起更新,从而导致其他触发器的激活。 触发级联是指, 一次插入、删除或更新操作可能会激活一系列重要的触发器,从而导致数据库发生重大变化
如果指定或接受 SHRLEVEL NONE 选项作为默认选项,则使用 LOAD 实用程序加载表格不会激活为该表格定义的任何触发器。 如果LOAD语句包含SHRLEVEL CHANGE选项,则在用LOAD实用程序加载表时触发器被激活。
- 添加触发器以强制执行约束:
- 在已经存在行的表格上添加触发器不会导致触发操作被执行。 因此,如果触发器旨在对表中的数据进行约束,则现有行中的数据可能不符合这些约束。
- 多重触发:
- 可以在表格中定义多个触发器,这些触发器具有相同的触发SQL操作和激活时间。 触发器按创建顺序依次激活。 例如,首先创建的触发器首先执行;其次创建的触发器其次执行。
- 过渡变量和过渡表:
- 触发操作可以参考受影响行集中的值。 通过使用过渡变量和过渡表来支持这一操作。
过渡变量的名称、数据类型和无效属性与触发器所定义的表中相应列的名称、数据类型和无效属性相同。 过渡变量包含受影响行中某一列的值。 转换变量由关联名称限定,该名称用于标识引用的是旧值(更新前)还是新值(更新后)。 在触发器主体的查询条件或 SQL 语句中可以引用过渡变量,前提是在触发器主体之外引用变量时允许使用该变量。 在更新或插入触发器中,可以为新的过渡变量赋值。 更新行的值包括在 before 触发器的触发动作中对过渡变量赋值所产生的变化。
转换表包含受影响行的完整集合:旧值(更新前)或新值(更新后)。 转换表是只读的, 可以在触发器动作之后或代替触发器引用。 转换表的列与触发器所定义的表的相应列具有相同的名称、数据类型和空属性。 转换表使用关联表标识符进行引用,该标识符允许将受影响行的完整集合视为一个表。 在触发器主体的搜索条件或SQL语句中可以引用转换表,前提是在触发器主体之外引用该表是允许的。 此外,转换表可以作为参数传递给用户定义的函数或过程,在转换表的表标识符前指定TABLE关键字。 当调用函数或过程时,会传递一个用于转换表的表定位符。
无论在 CREATE PROCEDURE 语句中将相应参数定义为 IN、INOUT 或 OUT,从触发操作中调用的存储过程返回的过渡变量或过渡表都不会受到影响。
表格定位器引用元素的注意事项:
不得在触发器正文中指定 table-locator-reference。
- 隐含隐藏列的注意事项:
- 在触发器主体中,可引用与隐式隐藏列对应的转换变量。 转换表与包含隐含隐藏列的表相对应,将隐含隐藏列作为转换表的一部分。 同样,对于定义为隐式隐藏的列,将存在一个过渡变量。 在触发器的主体中可以引用与隐含隐藏列对应的过渡变量。
- 识别码解析:
- 相同的名字应明确限定。 限定名称明确指出名称是指列、过渡变量还是全局变量。 如果名称不恰当或虽然恰当但仍然模糊不清,则按照以下规则解决。 如果为新旧过渡变量指定了相关名称,则必须使用相关联的相关名称来限定对过渡变量的引用。 按以下顺序检查匹配项,从而确定名称:
- 如果在创建触发器时,触发器主体中指定的表和视图已经存在,则首先在当前服务器上检查该名称是否为列名。 如果发现列名是某个名称,但用于发出CREATE语句的权限集没有访问表或视图的适当权限,则会返回错误。
- 如果列中没有找到该名称,则将其作为过渡变量名称进行检查。
- 如果未找到过渡变量,则将名称作为全局变量进行检查。
- 如果名称仍然无法解析,则返回错误。
- AFTER和INSTEAD OF触发器中过渡变量的注意事项:
- 在AFTER或INSTEAD OF触发器中不能修改过渡变量。
- 包裹失效:
- 根据指定的条款和关键字以及其他因素,此语句可能会使所有依赖于目标对象的程序包失效,有时还会通过级联效应影响其他相关对象。 更多信息,请参阅 “导致套餐失效的变更 ”。
- 无效缓存的动态 SQL 语句:
- 此语句可能会使依赖于目标对象的缓存动态 SQL 语句失效,有时还会通过级联效应影响其他相关对象。 更多信息,请参阅 “动态语句缓存失效 ”。
- INSTEAD OF触发器的注意事项:
- 添加一个代替触发器会影响视图的只读特性。 如果只读视图与INSTEAD OF触发器存在依赖关系,则INSTEAD OF触发器定义的操作类型将决定该视图是可删除、可插入还是可更新。
如果视图定义不是只读的,则创建一个“INSTEAD OF”触发器会导致动态语句缓存中的相关包、计划和语句被标记为无效。
在“代替插入”触发器中可见的新过渡变量或新过渡表列的初始值设置如下:
- 如果在插入操作中为列明确指定了值,则相应的新过渡变量就是该明确指定的值。
- 如果在插入操作中未明确指定列的值,或者指定了 DEFAULT 子句,则相应的新过渡变量为:
- 如果视图列可更新(没有INSTEAD OF触发器),则为基础表列的默认值
- 否则,空值
如果视图列不可为空且没有默认值,则必须在插入操作中明确指定该值。
在“代替更新”触发器中可见的新过渡变量的初始值设置如下:
- 如果在更新操作中为某一列明确指定了值,则相应的新过渡变量就是该明确指定的值
- 如果在更新操作中为某一列明确指定了默认条款,则相应的新转换变量为:
- 如果视图列可更新(没有INSTEAD OF触发器),则为基础表列的默认值
- 否则,空值
如果视图列不可为空且没有默认值,则必须在更新操作中明确指定该值。
- 否则,相应的新的过渡变量就是该行中列的现有值。
- MERGE语句注意事项:
MERGE 语句可以执行插入、删除和更新操作。
在执行数据更改操作时,会为 MERGE 语句激活适用的触发器。- 对于包含XML列的表格中定义的触发器的注意事项:
- 虽然可以在包含XML列的表格中定义触发器:
触发器主体中的触发器转换变量不能引用 XML 列。 
触发器正文中不能引用过渡表的 XML 列。 
- 使用SECURED选项创建触发器:
- 通常,安全管理员会检查触发器访问的数据,确保其安全,并向需要创建安全触发器权限的人员授予CREATE_SECURE_OBJECT权限。 触发器创建后,安全管理员将撤销触发器所有者的CREATE_SECURE_OBJECT权限。
CREATE TRIGGER语句执行后,触发器即被视为安全。 Db2 将SECURED属性视为一个断言,声明用户已为触发器主体中的所有活动建立了审计程序。 如果安全触发器引用了用户定义的函数,则 Db2 会认为这些函数无需验证即可安全使用。 如果这些功能可以访问敏感数据,那么拥有SECADM权限的用户需要确保这些功能被允许访问这些数据,并且这些功能的所有版本都经过审计,而且所有后续的ALTER FUNCTION语句或对外部包的更改都经过审计流程的审查。
如果触发器的目标表使用行访问控制或列访问控制,则触发器必须安全。 如果为视图创建的触发器,且视图定义中一个或多个基础表使用行访问控制或列访问控制,则必须指定SECURED。
- 使用“未上锁”选项创建触发器:
- 如果触发器的目标表使用行访问控制或列访问控制,或者触发器用于视图,并且视图定义中的一个或多个基础表使用行访问控制或列访问控制,则CREATE TRIGGER语句将返回错误。
- 对于过渡变量和过渡表,不强制执行行和列访问控制:
- 如果对触发器的目标表实施了行访问控制或列访问控制,则行权限和列掩码不适用于转换变量和转换表的初始值。 触发表的行访问控制和列访问控制是强制性的,但对于在触发器主体中引用的过渡变量和过渡表,或者作为参数传递给在触发器主体中调用的用户定义函数,则忽略这些变量和表。 为了确保在触发器操作中访问过渡变量和过渡表中的敏感数据的SQL语句不存在安全问题,必须使用SECURED选项创建触发器。 如果触发器不安全,CREATE TRIGGER语句将返回错误。
- 涉及待定义变更的限制:
- 如果触发器定义在存在待定义更改的表上,则不允许创建触发器。
- EXPLAIN的特殊计划、语句和功能表的注意事项:
- 您可以在PLAN_TABLE、DSN_STATEMNT_TABLE或DSN_FUNCTION_TABLE上创建触发器。 但是,当 Db2 向表中添加行时,这些表中定义的插入触发器不会被激活。
- 从属对象:
- 触发器取决于触发表和触发器主体中引用的对象。
- 在触发操作中添加一个列到主题表或引用表中:
- 如果在定义触发器后向主题表中添加列,则适用以下规则:
- 如果触发器是一个没有明确列名列表的更新触发器,则对新列的更新将激活触发器。
- 如果触发操作中引用了主题表,则在重新编译触发器包之前,SQL语句无法访问新列。
- OLD_TABLE和NEW_TABLE转换表包含新列,但除非重新创建触发器,否则无法引用该列。 如果转换表被传递给用户定义的函数或存储过程,则必须使用新的表定义重新创建用户定义的函数或存储过程(即必须删除并重新创建函数或存储过程),并且必须重新绑定用户定义的函数或存储过程的包。
如果在触发操作中引用的任何表中添加列,则在新列重新绑定触发器包之前,SQL语句无法访问该列。
- 从主题表或触发操作中引用的表中删除一列:
- 对于定义了触发器的表,不能删除列。
- 更改触发操作所引用的列的属性:
- 如果定义触发器的表(主表)中的列发生改变,则触发器将处理该改变,并使相关触发器包失效。
- 重命名已定义触发器的表,或触发操作中引用的表:
- 您不能重命名已定义触发器的表(主题表)。 除了主题表,您可以重命名触发操作中SQL语句引用的任何表。 重命名表后,放下触发器,然后重新创建触发器,使其指向重命名的表。
- 删除已定义触发器的表格或视图:
- 如果触发器所定义的表或视图被删除,则触发器也会被删除。
- 在触发操作中 ,删除或撤销对引用对象的权限会产生以下影响:
- 删除触发器正文中引用的对象,或撤销触发器正文中引用的对象的权限,可能会产生以下结果:
- 在触发操作中,删除SQL语句中引用或使用的任何表、视图、别名或索引,都会导致触发器及其包失效。
- 删除一个已引用的同义词不会对触发器或其包产生任何影响。
- 不允许删除触发操作中SQL语句引用的用户自定义函数。 发生错误。
- 不允许删除触发操作中SQL语句引用的序列。 发生错误。
- 撤销触发器所依赖的特权会导致触发器及其组件失效。 如果在触发器包被重置时不存在适当的权限,则引用该对象的SQL语句将失败。
- 触发器中的错误处理:
- 触发器可能会返回错误,就像其他SQL语句一样。 应用程序需要考虑触发器被调用时可能出现的错误。
- 触发器和全局变量:
- 触发器引用的全局变量的内容从触发SQL操作(删除、插入或更新)继承而来。
- 特别登记:
- 当触发器被激活时,触发器主体中特殊寄存器的值被确定。 CURRENT PACKAGESET特殊寄存器的值设置为触发器的模式名称,其他特殊寄存器的值从触发SQL操作(插入、更新或删除)继承。 当触发器被激活时,特殊寄存器值被保存,并在触发器返回时恢复。 当前日期、当前时间和当前时间戳特殊寄存器在触发器返回时不会恢复。
- 存储过程的执行结果集:
- 如果触发器调用一个返回结果集的存储过程,则激活触发器的应用程序无法访问这些结果集。
- 交易隔离:
- SQL触发器主体中的所有语句都在对触发器有效的隔离级别下运行。
- 限制处理器时间:
通过 Db2 资源限制功能,可以指定 SELECT 或 SQL 数据更改语句等动态、可操作 SQL 语句的最大处理器时间。 触发器的执行被视为触发 SQL 语句的一部分。 
- 绑定触发器的错误:
- 绑定CREATE TRIGGER语句时,触发操作中的SQL语句可能无法完全解析。 这些语句中的语法错误可能直到执行CREATE TRIGGER语句时才会被发现。
- 为触发器生成的包的特征:
- 与触发器关联的包的命名如下:
- 位置设置为当前服务器特殊寄存器的值。
- 包的collection-id (模式)与触发器的模式限定符相同。
- package-id 与触发器的名称相同。
- version-id 为空字符串。
Db2 创建的触发器包具有以下初始属性(其中部分属性可使用 REBIND TRIGGER PACKAGE 命令修改):

- 操作(添加)
- 档案敏感(是)
- 对时间敏感(是)
- 当前数据(否)
- dbprotocol(drda)
- 程度(1)
- DESCSTAT(DESCSTAT子系统参数的值)
- DYNAMICRULES(BIND)
- 启用(*)
- 编码(0)
- 解释(否)
- FLAG(I)
- 绝缘(CS)
- REOPT(NONE)
- 不服从(准备)
- OPTHINT
- 所有者(授权ID)或角色
- 路径(path)
- 发布(提交)
- 舍入(当前DECFLOAT舍入模式特殊寄存器的值)
- sqlerror(nopackage)
- 系统灵敏度(是)
- 资格认证(授权ID)
- 确认(绑定)

OWNER、QUALIFIER 和 PATH 的值取决于 CREATE TRIGGER 语句是嵌入在程序中还是以交互方式发出。 如果语句嵌入程序中,OWNER和QUALIFIER是包或计划的所有者和限定符。 PATH是PATH绑定选项的值。 如果语句是交互式发出的,则OWNER和QUALIFIER都是SQL授权ID。 PATH 是当前路径(CURRENT PATH)特殊寄存器中的值。
不允许一个触发包有多个版本。 使用REBIND TRIGGER PACKAGE命令重新绑定基本触发器包。 要为绑定命令指定触发器包的名称,触发器名称必须符合普通标识符的规则。
如果触发器所依赖的对象或权限被删除或撤销,则触发器包将失效。 下次触发器被激活时, Db2 将尝试重新绑定无效的触发器包。 如果自动重新绑定失败,触发器包将保持无效状态。
您无法从触发器包中创建另一个包,例如使用BIND COPY命令。 放下触发器套件的唯一方法是放下触发器或主体台。 放下扳机,扳机组件就会掉落;放下主题表,扳机和扳机组件就会掉落。
每次触发器被激活时,触发器组件都会执行一次或多次。
- SQL处理器程序的注意事项:
- SQL处理器程序(例如SPUFI、 Db2 command line processor 和 DSNTEP2 )可能无法正确解析触发操作中以分号结尾的SQL语句。 这些处理器程序接受多个SQL语句作为输入,每个语句以一个终止符分隔。 使用分号作为SQL语句终止符的处理器程序可能会截断带有嵌入分号的CREATE TRIGGER语句,仅将其中一部分传递给 Db2。 因此,您可能需要为这些处理器程序更改 SQL 终止符。 有关更改SPUFI和 DSNTEP2 的终止符的信息,请参阅 《在SPUFI输入数据集中设置SQL终止符 》以及 DSNTEP2 和 DSNTEP4 示例程序。
应用程序兼容性级别:
触发器主体中的 SQL 语句必须符合生效的应用程序兼容性选项指定的行为。 用于处理触发器的应用程序兼容性值记录在 SYSIBM.SYSPACKAGE 目录表的 APPLCOMPAT 列中。
- 其他语法和同义词:
- 为了与 Db2 的早期版本或 Db2 系列中的其他产品兼容, Db2 支持以下关键词:
- OLD TABLE作为OLD_TABLE的同义词
- NEW TABLE作为NEW_TABLE的同义词
混淆视听的发言:
FL 500A CREATE TRIGGER 语句可以混淆形式执行。 在一份模糊不清的声明中,只有触发器名称和WRAPPED关键字可以读取。 该语句的其余部分将以不可读方式进行编码,但支持模糊语句的数据库服务器可以解码该部分。 WRAP标量函数生成混淆语句。 根据混淆语句创建触发器时指定的任何调试选项都会被忽略。
CREATE TRIGGER(基本)示例
- 示例 1
创建两个触发器,用于跟踪公司管理的员工数量。 主表是员工表,触发器根据公司统计表中的员工总数来增减列。 表格包含以下列:
- 员工表:ID、姓名、地址和职位
- COMPANY_STATS表:NBEMP、NBPRODUCT和REVENUE
这个示例展示了如何在行触发器中使用过渡变量来维护另一个表中的汇总数据。
创建第一个触发器 NEW_HIRE,使其在每次有新人被雇佣时都会增加雇员人数;也就是说,每次在 EMPLOYEE 表中插入新记录时,都会将 COMPANY_STATS 表中 NBEMP 列的值增加 1。
CREATE TRIGGER NEW_HIRE AFTER INSERT ON EMPLOYEE FOR EACH ROW MODE DB2SQL BEGIN ATOMIC UPDATE COMPANY_STATS SET NBEMP = NBEMP + 1; END
创建第二个触发器 FORM_EMP,以便在每次有员工离职时递减员工人数;也就是说,每次从表 EMPLOYEE 中删除一条记录时,将表 COMPANY_STATS 中 NBEMP 列的值减少 1。
CREATE TRIGGER FORM_EMP AFTER DELETE ON EMPLOYEE FOR EACH ROW MODE DB2SQL BEGIN ATOMIC UPDATE COMPANY_STATS SET NBEMP = NBEMP - 1; END
- 示例 2
创建一个触发器“REORDER”,每当零件记录更新且受影响零件的现有数量少于其最大库存量的10%时,该触发器将调用用户定义的函数ISSUE_SHIP_REQUEST来发出发货请求。 用户自定义函数ISSUE_SHIP_REQUEST用于订购零件数量,该数量等于零件的最大库存量减去现有数量;该函数还确保将请求发送给相应的供应商。
零件记录在零件表中。 虽然表格列数更多,但只有在ON_HAND和MAX_STOCKED列更新时才会触发。

CREATE TRIGGER REORDER AFTER UPDATE OF ON_HAND, MAX_STOCKED ON PARTS REFERENCING NEW AS NROW FOR EACH ROW MODE DB2SQL WHEN (NROW.ON_HAND < 0.10 * NROW.MAX_STOCKED) BEGIN ATOMIC VALUES(ISSUE_SHIP_REQUEST(NROW.MAX_STOCKED - NROW.ON_HAND, NROW.PARTNO)); END
- 示例 3
重复示例2中的场景,但使用fullselect代替VALUES语句来调用用户定义的函数。 这个示例还展示了如何将触发器定义为语句触发器,而不是行触发器。 对于转换表中WHERE子句计算结果为true的每一行,都会发出零件的运输请求。

CREATE TRIGGER REORDER AFTER UPDATE OF ON_HAND, MAX_STOCKED ON PARTS REFERENCING NEW_TABLE AS NTABLE FOR EACH STATEMENT MODE DB2SQL BEGIN ATOMIC SELECT ISSUE_SHIP_REQUEST(MAX_STOCKED - ON_HAND, PARTNO) FROM NTABLE WHERE (ON_HAND < 0.10 * MAX_STOCKED); END
- 示例 4
- 假设表EMPLOYEE包含列SALARY。 创建一个触发器SAL_ADJ,防止员工工资更新超过20%,并发出错误信号。 错误信息为SQLSTATE '75001',并附带描述。 本例说明,SIGNAL 语句可用于限制违反业务规则的更改。

CREATE TRIGGER SAL_ADJ AFTER UPDATE OF SALARY ON EMPLOYEE REFERENCING OLD AS OLD_EMP NEW AS NEW_EMP FOR EACH ROW MODE DB2SQL WHEN (NEW_EMP.SALARY > (OLD_EMP.SALARY * 1.20)) BEGIN ATOMIC SIGNAL SQLSTATE '75001' ('Invalid Salary Increase - Exceeds 20'); END
- 示例 5
- 假设以下语句创建了一个表 WEATHER(存储华氏温度值)和一个视图 CELSIUS_WEATHER,供那些习惯使用摄氏温度而非华氏温度的用户使用:
在 CELSIUS_WEATHER 视图中使用以下 INSTEAD OF 触发器将摄氏度值转换为华氏度值,然后将华氏度值插入 WEATHER 表:CREATE TABLE WEATHER (CITY VARCHAR(25), TEMPF DECIMAL(5,2)); CREATE VIEW CELSIUS_WEATHER (CITY, TEMPC) AS SELECT CITY, (TEMPF-32)/1.8 FROM WEATHER;
CREATE TRIGGER CW_INSERT INSTEAD OF INSERT ON CELSIUS_WEATHER REFERENCING NEW AS NEWCW FOR EACH ROW MODE DB2SQL BEGIN ATOMIC INSERT INTO WEATHER VALUES (NEWCW.CITY, 1.8*NEWCW.TEMPC+32); END

例 6

考虑一个记录和跟踪股票价格变化的应用程序。 数据库包含两个表:CURRENTQUOTE 和 QUOTEHISTORY。 CURRENTQUOTE包含SYMBOL、QUOTE和STATUS列。 QUOTEHISTORY包含SYMBOL、QUOTE和QUOTE_TIMESTAMP列。当“当前报价”的“报价”列更新时,必须将带有时间戳的新报价复制到“报价历史”表中。 此外,必须更新当前报价的“状态”栏,以反映库存是否:

1 价值上升 2 创下年度新高 3 贬值 4 创下年度新低 5 价值稳定 
完成这些任务的CREATE TRIGGER语句如下:
触发器 STOCK_STATUS 用于设置状态:
CREATE TRIGGER STOCK_STATUS NO CASCADE BEFORE UPDATE OF QUOTE ON CURRENTQUOTE REFERENCING NEW AS NEWQUOTE OLD AS OLDQUOTE FOR EACH ROW MODE DB2SQL BEGIN ATOMIC SET NEWQUOTE.STATUS = CASE WHEN NEWQUOTE.QUOTE > (SELECT MAX(QUOTE) FROM QUOTEHISTORY WHERE SYMBOL = NEWQUOTE.SYMBOL AND YEAR(QUOTE_TIMESTAMP) = YEAR(CURRENT DATE) ) THEN 'High' WHEN NEWQUOTE.QUOTE < (SELECT MIN(QUOTE) FROM QUOTEHISTORY WHERE SYMBOL = NEWQUOTE.SYMBOL AND YEAR(QUOTE_TIMESTAMP) = YEAR(CURRENT DATE) ) THEN 'Low' WHEN NEWQUOTE.QUOTE > OLDQUOTE.QUOTE THEN 'Rising' WHEN NEWQUOTE.QUOTE < OLDQUOTE.QUOTE THEN 'Dropping' WHEN NEWQUOTE.QUOTE = OLDQUOTE.QUOTE THEN 'Steady' END; END触发器 RECORD_HISTORY 记录 QUOTEHISTORY 表中的更改:
CREATE TRIGGER RECORD_HISTORY AFTER UPDATE OF QUOTE ON CURRENTQUOTE REFERENCING NEW AS NEWQUOTE FOR EACH ROW MODE DB2SQL BEGIN ATOMIC INSERT INTO QUOTEHISTORY VALUES (NEWQUOTE.SYMBOL, NEWQUOTE.QUOTE, CURRENT TIMESTAMP); END
