触发器

触发器是一种特殊的存储过程,一种不能被显式执行,而必须依附于一个事件的过程。只要事件发生,就会调用触发器,运行它的代码。SQL Server 支持把触发器和两种类型的事件关联:数据操作事件(如INSERT)和数据定义事件(如CREATE TABLE),和这两种事件关联的触发器分别称为DML 触发器和DDL 触发器。

触发器有很多用途,包括审核数据、实施不能通过约束而实现的完整性规则、实施一定的策略,等等。

可以把触发器看成是某个事务的一个组成部分,该事务包含能够触发触发器的事件。在触发器的代码中执行ROLLBACK TRAN 命令将会导致触发器内发生的所有更改,以及和触发器关联的事务中进行的所有更改都发生回滚。

在SQL Server中,触发器是按照语句触发的,而不是按照被修改的行而触发的。

1. DML触发器

SQL Server 支持两种DML触发器:AFTER 触发器和INSTEAD OF 触发器。AFTER 触发器是在与之关联的事件完成后才触发的,只能在持久化的表上定义这种触发器。INSTEAD OF 触发器的触发是为了代替与之关联的事件操作,可以在持久化的表或视图上定义这种类型的触发器。

在触发器代码中,可以访问称为inserted和deleted的两个表,它们包含导致触发器触发修改操作而影响的记录行。inserted 表包含当执行INSERT和UPDATE 语句时受影响行的新数据的镜像。deleted表则包含当执行DELETE和UPDATE语句时受影响行的旧数据的镜像。对于INSTEAD OF 触发器,inserted和deleted表包含导致触发器触发的修改操作打算要影响的行。

CREATE TRIGGER trg_T1_insert_audit ON dbo.T1 AFTER INSERT

AS

SET NOCOUNT ON;

INSERT INTO dbo.T1_Audit(keycol,datacol)

  SELECT keycol,datacol FROM inserted;

GO

2. DDL 触发器

SQL Server 2005 引入了对DDL 触发器的支持,它们可以用于在数据库中执行审核、增强策略、变化管理等任务。

SQL Server 支持在两个作用域内创建DDL 触发器(数据库作用域和服务器作用域),这要取决于事件的作用域。例如,对于数据库作用域的事件(如CREATE TABLE),可以创建数据库作用域内的触发器;对于具有服务器作用域的事件(如CREATE DATABASE),可以创建服务器作用域内的触发器。SQL Server只支持AFTER类型的DDL触发器,而不支持BEFORE或INSTEAD OF 类型的DDL触发器。

在触发器中,通过查询EVENTDATA函数(该函数将事件信息作为XML值返回),可以获取关于导致触发器触发的事件信息。再用XQuery表达式从XML 值中提取各种事件属性,如提交时间、事件类型、登录名称等。

在数据库上通过事件组DDL_DATABASE_LEVEL_EVENTS 来创建审核触发器trg_audit_ddl_events,这个事件组代表数据库级上的所有DDL事件:

 CREATE TRIGGER trg_audit_ddl_events

  ON DATABASE FOR DDL_DATABASE_LEVEL_EVENTS

AS

SET NOCOUNT ON;

DECLARE @eventdata AS XML;

SET @eventdata=eventdata();

INSERT INTO dbo.AuditDDLEvents(

  posttime,eventtype,loginname,schemaname,objectname,targetobjectname,eventdate)

  VALUES(

    @eventdata.value('(/EVENT_INSTANCE/PostTime)[1]',     'VARCHAR(23)'),

    @eventdata.value('(/EVENT_INSTANCE/EventType)[1]',     'sysname'),

    @eventdata.value('(/EVENT_INSTANCE/LoginName)[1]',     'sysname'),

    @eventdata.value('(/EVENT_INSTANCE/SchemaName)[1]',     'sysname'),

    @eventdata.value('(/EVENT_INSTANCE/ObjectName)[1]',     'sysname'),

    @eventdata.value('(/EVENT_INSTANCE/TargetObjectName)[1]',     'sysname'),

    @eventdata);

GO

posted @ 2014-06-22 19:56  守护之翼  阅读(187)  评论(0编辑  收藏  举报