对 DML 触发器进行编程

几乎所有可以编写成批处理的 Transact-SQL 语句都可用于创建 DML 触发器,下列语句除外。

ALTER DATABASE

CREATE DATABASE

DROP DATABASE

LOAD DATABASE

LOAD LOG

RECONFIGURE

RESTORE DATABASE

RESTORE LOG

 

ms190227.note(zh-cn,SQL.90).gif重要提示:
SQL Server 2005 中包括的 LOAD DATABASE 和 LOAD LOG 语句仅用于实现向后兼容性,以后可能不受支持。

此外,在对作为触发操作的目标的表或视图使用下列 Transact-SQL 语句时,将不允许在 DML 触发器的主体内使用这些语句:

ms190227.note(zh-cn,SQL.90).gif重要提示:
尽管 SQL Server 2005 中引入了此限制,但是当向后兼容模式设置为 80 时,仍会强制实施。

CREATE INDEX

ALTER INDEX

DROP INDEX

DBCC DBREINDEX

ALTER PARTITION FUNCTION

DROP TABLE

ALTER TABLE 用于:

  • 添加、修改或删除列。
  • 切换分区。
  • 添加或删除主键或唯一约束。

 

 

对 DML 触发器定义进行模糊处理

若要对 CREATE TRIGGER 语句的原始文本进行模糊处理,请使用 WITH ENCRYPTION 选项。 模糊操作的输出在 SQL Server 2005 的任何系统表或视图中都不直接显示。 对系统表、系统视图或数据库文件没有访问权限的用户不能检索经过模糊的文本。 但是,可直接访问数据库文件的特权用户可以查看到该文本。 这些用户可能会对模糊代码进行反向工程处理以检索触发器定义的原始文本。

使用 WITH ENCRYPTION 可以防止将触发器作为 SQL Server 复制的一部分进行发布。

SET 语句选项

当 ODBC 应用程序连接到 SQL Server 时,服务器将自动为会话设置下列选项:

  • SET QUOTED_IDENTIFIER ON
  • SET TEXTSIZE 2147483647
  • SET ANSI_DEFAULTS ON
  • SET CURSOR_CLOSE_ON_COMMIT OFF
  • SET IMPLICIT_TRANSACTIONS OFF

这些设置会增加 ODBC 应用程序的可移植性。 因为基于 DB-Library 的应用程序通常不设置这些选项,所以应使用上面列出的 SET 选项(设置为 ON 和 OFF)测试触发器。 这可以确保触发器正常工作,而无论特定连接在调用触发器时设置的选项如何。 如果触发器需要为这些选项之一进行特殊设置,则应该在触发器启动时发出 SET 语句。 此 SET 语句仅在触发器执行期间有效,触发器完成后,即恢复原始设置。

测试对特定列的更改

UPDATE() 函数可用于确定 INSERT 或 UPDATE 语句是否影响表中的特定列。 无论何时为列赋值,该函数都将返回 TRUE。

ms190227.note(zh-cn,SQL.90).gif注意:
由于使用 DELETE 语句无法删除列中的特定值,因此不能将 IF UPDATE() 子句应用于 DELETE 语句。

此外,COLUMNS_UPDATED 函数也可用于检查 INSERT 或 UPDATE 语句更新了表中的哪些列。 此函数使用整数位掩码指定要测试的列。 有关详细信息,请参阅 CREATE TRIGGER

示例

A. 使用 IF UPDATE() 子句测试数据修改

下面的示例对表 my_table 创建了 INSERT 触发器 my_trig,并测试列 b 是否受任何 INSERT 尝试的影响。

CREATE TABLE my_table*
(a int NULL, b int NULL)
GO

CREATE TRIGGER my_trig
ON my_table
FOR INSERT
AS
IF UPDATE(b)
   PRINT 'Column b Modified'
GO

B. 使用 COLUMNS UPDATED 函数测试数据修改

下面的示例使用 COLUMNS_UPDATED() 子句获得类似的结果。

CREATE TRIGGER my_trig2
ON my_table
FOR INSERT
AS
IF ( COLUMNS_UPDATED() & 2 = 2 )
   PRINT 'Column b Modified'
GO

延迟的名称解析

DML 触发器可以引用触发器创建时不存在的表。 这称为“延迟的名称解析”。 有关延迟的名称解析的详细信息,请参阅延迟名称解析和编译

ms190227.note(zh-cn,SQL.90).gif注意:
如果 DML 触发器引用的对象已删除或重命名,则执行触发器时会返回错误。 但是,如果 DML 触发器中引用的对象被替换为同名对象,则不必重新创建即可执行触发器。 例如,如果触发器 trig1 引用表 test1,在删除 test1 表后,创建一个名为 test1 的不同的表,则 trig1 在执行时会引用新表。

返回结果

建议 DML 触发器不返回任何结果。 这是因为对这些返回结果的特殊处理必须写入每个允许对触发器表进行修改的应用程序中。 若要防止从 DML 触发器返回任何结果,请不要在触发器定义中包含 SELECT 语句或变量赋值。 如果必须在触发器中进行变量赋值,则应该在触发器之前使用 SET NOCOUNT 语句以避免返回任何结果集。

ms190227.note(zh-cn,SQL.90).gif重要提示:
未来版本的 SQL Server 中会删除从触发器返回结果集的功能。 请避免在新的开发工作中从触发器返回结果集,并考虑修改目前具有此行为的应用程序。 若要在 SQL Server 2005 中防止从触发器返回结果集,请将disallow results from triggers 选项设置为 1。在未来版本的 SQL Server 中,此选项的默认设置将为 1。

请参阅

其他资源

CREATE TRIGGER (Transact-SQL)
SELECT (Transact-SQL)
SET (Transact-SQL)

帮助和信息

获取 SQL Server 2005 帮助

更改历史记录

发布日期 历史记录
更改的内容:
  • 用“Obfuscating DML Trigger Definitions”(对 DML 触发器定义进行模糊处理)替换了“Encrypting DML Trigger Definitions”(对 DML 触发器定义进行加密)。