触发器的特征:

1、触发器是在对表进行增、删、改时,自动执行的存储过程。触发器常用于强制业务规则,它是一种高级约束,通过事件进行触发而被执行。

2、触发器是一个特殊的事务单元,可以引用其他表中的列执行特殊的业务规则或数据逻辑关系。当出现错误时,可以执行rollback transaction操作将整个触发器以及触发它的T-SQL语句一并回滚(不需显示声明begin transaction)。

3、每个触发器将用到的两个临时表

   deleted 临时表:用于临时存放被删除的记录行副本(包括delete和update语句所影响的数据行);

                  注意:被删除的记录行,首先从原始表中删除,并保存到触发器表。然后从触发器表中删除,再保存到deleted表。
   inserted临时表:用于临时存放插入的记录行副本(包括insert和update语句所影响的数据行);
    deleted表和inserted表的特征:
    > 这两个表的表结构与该触发器作用的表相同;
    > 这两个表是逻辑表,并且由系统管理;
    > 这两个表是动态驻留在内存中的(不是存储在数据库中),当触发器工作完成后,它们也被删除;
    > 这两个表是只读的,即只能运用select语句查看(用户不能直接更改);
4、所创建的触发器(insert、delete、update)是在原表数据行已经修改完成后再触发。所以,触发器是在约束检查之后才执行。
什么时候使用触发器?
a、实现主外键关系所不能保证的复杂参照完整性数据的一致性。
    不过,通过“级联引用完整性约束”可以更有效地执行这些更改。
b、防止恶意或错误的 INSERT、UPDATE 以及 DELETE 操作,并强制执行比 CHECK 约束定义的限制更为复杂的其他限制。
   > 与 CHECK 约束不同(check约束只能引用自身表中的列),DML触发器可以引用其他表中的列
   > 触发器可以完成所有约束的功能,但不一定是最佳方案;
   > 触发器能够使用自定义信息和较为复杂的错误处理
c、DML 触发器可以评估数据修改前后表的状态,并根据该差异采取措施。
d、一个表中的同一个修改语句的DML触发器,允许被多个不同的操作(INSERT、UPDATE 或 DELETE)来响应
触发器的类型:
insert 触发器;(略)
delete 触发器;(略)
update 触发器:在修改表中记录行或某列数据时触发执行;
注意:update(列)函数:实现检测某列是否被修改。
update 更新操作分为两步:
首先,“删除”更改前原有数据行:删除的原有数据行将复制到deleted临时表中;
然后,“插入”更改后的新数据行:插入新数据行到原始表,同时将新数据行保存到inserted临时表和触发器表中;
创建触发器的注意点:
1、create trigger必须是批处理(go)的第一条语句;
2、一个触发器语句只能用到一个表或一个视图中;
   on 表名/ 视图名
3、一个触发器语句可以执行多个操作;
   for delete,insert,update -- 无先后顺序的任意组合
4、建议DML触发器不返回任何结果。这是因为对这些返回结果的特殊处理必须写入每个允许对触发器表进行修改的应用程序中。
     若要防止从 DML 触发器返回任何结果,请不要在触发器定义中包含select语句或变量赋值;
     如果必须在触发器中进行变量赋值,则应该在触发器被触发之前使用set nocount on语句以避免返回任何结果集;
注意:未来版本的SQL Server 中,将会删除从触发器返回结果集的功能。
5、如果“触发器表”本身也存在约束,则在执行insert、delete、update触发器前,首先会检查“触发器表”上存在的约束。如果不满足约束,则不会执行其insert、delete、update触发器。

查看当前数据库中的所有触发器

 
  1. select * from sys.triggers 

创建临时表 #tableName

 
  1. create table #tableName 
 
如何使用 SQL Server 触发器

触发器2_初始化环境SQL

 
  1. --------------- 初始化环境 --------------- 
  2.  
  3. create database TriggerDatabase 
  4. use TriggerDatabase 
  5. go 
  6.  
  7. if exists(select * from sysobjects where name='bank'
  8.    drop table bank 
  9.  
  10. create table bank -- 账户信息表 
  11.    userName      varchar(10) not null,  --顾客名 
  12.    cardID        varchar(10) not null,  --卡号 
  13.    currentMoney  money       not null   --当前余额 
  14.  
  15. if exists(select * from sysobjects where name='transInfo'
  16.    drop table transInfo 
  17.  
  18. create table transInfo --交易信息表 
  19.    cardID     varchar(10) not null,  --卡号 
  20.    transType  char(4)     not null,  --交易类型(存入/支取) 
  21.    transMoney money       not null,  --交易金额 
  22.    transDate  datetime    not null   --交易日期 
  23. go 
  24.  
  25. --------------- 添加约束 --------------- 
  26. alter table bank 
  27. add constraint CK_currentMoney check(currentMoney>=1); 
  28.  
  29. alter table transInfo 
  30. add constraint DF_transDate default(getdate()) for transDate; 
  31.  
  32. alter table transInfo 
  33. add constraint CK_transType check(transType in('支取','存入')); 
  34.  
  35. --------------- 添加测试数据 --------------- 
  36. /* 张三 1000元 */ 
  37. insert into bank(userName,cardID,currentMoney) 
  38.         values('张三','1001 0001',1000); 
  39. /* 李四 1元 */ 
  40. insert into bank(userName,cardID,currentMoney) 
  41.         values('李四','1001 0002',1); 
  42. /* 张三 支取 200元 */ 
  43. insert into transInfo(cardID,transType,transMoney) 
  44.         values('1001 0001','支取',200); 
  45.  
  46. --------------- 查看结果 --------------- 
  47. select * from bank; 
  48. select * from transInfo; 
  49. go 

触发器3_定义触发器的格式

 
  1. -- ============================================= 
  2. -- Author:        xugang 
  3. -- Create date: 2010-2-14 
  4. -- Description:    定义触发器的精简格式 
  5. --  [ ]:可选     { }必选 
  6. -- ============================================= 
  7.  
  8. create trigger [ schema_name. ] -- 触发器所属架构 
  9.                trigger_name     -- 触发器名称 
  10. on { table | view }       -- 触发器的表或视图 
  11.    [ with encryption ]    -- 加密dml触发器定义(后面详解) 
  12. for | after }  
  13.    /* after:只有在触发它的SQL语句执行成功后才能激发。 
  14.              (只能对“表”定义after) */ 
  15.     { insert,update,delete }  
  16. as 
  17.     /* SQL语句... */ 
  18. go 
  19.  
  20.  
  21.  
  22. --查看当前数据库中的所有触发器 
  23. select * from sys.triggers 

触发器4_insert 触发器SQL

 
  1. ------------------ insert 触发器 ------------------ 
  2. use TriggerDatabase 
  3. go 
  4. if exists(select * from sysobjects  
  5.            where name='trig_insert_transInfo'
  6. drop trigger trig_insert_transInfo 
  7. go 
  8.  
  9. -- create trigger必须是批处理(go)的第一句 
  10.  
  11. create trigger trig_insert_transInfo 
  12. on transInfo for insert 
  13. as 
  14.     declare @_transType   char(4),  --定义变量 
  15.             @_transMoney  money, 
  16.             @_cardID      char(10), 
  17.             @balance      money     --所剩余额 
  18.  
  19.     -- 从inserted临时表中获取记录值 
  20.     select @_transType = transType, 
  21.            @_transMoney = transMoney, 
  22.            @_cardID = cardID  
  23.            from inserted 
  24.  
  25.     if(@_transType = '支取'
  26.        update bank set currentMoney=currentMoney-@_transMoney 
  27.               where cardID = @_cardID; 
  28.     else  
  29.        update bank set currentMoney=currentMoney+@_transMoney 
  30.               where cardID = @_cardID; 
  31.  
  32.     --显示交易金额 
  33.     print '交易成功! 交易金额:' 
  34.           + convert(varchar(20),@_transMoney) 
  35.  
  36.     --显示所剩余额 
  37.     select @balance = currentMoney from bank  
  38.            where cardId = @_cardID 
  39.  
  40.     print '卡号:'+@_cardID  
  41.           + ' 余额:'+convert(varchar(20),@balance); 
  42. go 
  43.  
  44.  
  45.  
  46. ------------------ 测试触发器 ------------------ 
  47.  
  48. -- delete from transInfo 
  49. set nocount on --不显示T-SQL影响的记录行数 
  50.  
  51. insert into transInfo(cardID,transType,transMoney) 
  52.              values('1001 0001','支取',200); 
  53. insert into transInfo(cardID,transType,transMoney) 
  54.              values('1001 0001','存入',10000); 
  55. --查看结果 
  56. select * from bank 
  57. select * from transInfo 

触发器5_delete 触发器SQ L

 
  1. /* 实现: 当清除'交易信息表'的数据时, 
  2.          自动备份被清除的数据到backupTable表中 
  3. */ 
  4.  
  5. ------------------ delete 触发器 ------------------ 
  6. use TriggerDatabase 
  7. go 
  8.  
  9. if exists (select * from sysobjects  
  10.            where name='trig_delete_transInfo'
  11. drop trigger trig_delete_transInfo 
  12. go 
  13.  
  14. create trigger trig_delete_transInfo 
  15. on transInfo after delete  --  for | after 
  16. as 
  17.    print '开始备份数据,请稍后......' 
  18.    -- 如果数据库中,不存在 backupTable 表 
  19.    if not exists(select * from sysobjects  
  20.                   where name='backupTable'
  21.       select * into backupTable from deleted --deleted临时表 
  22.    else 
  23.       insert into backupTable select * from deleted 
  24.    
  25.    print '备份成功,备份表 backupTable 中的数据为:' 
  26.         select * from backupTable; 
  27. go 
  28.  
  29.  
  30. ------------------ 测试触发器 ------------------ 
  31. set nocount on 
  32.  
  33. delete from transInfo; --测试 
  34.  
  35. --查看结果 
  36. select * from transInfo 
  37. select * from backupTable 

触发器6_update 触发器SQL

 
  1. ------------------ update 触发器 ------------------ 
  2. use TriggerDatabase 
  3. go 
  4.  
  5. if exists (select * from sysobjects  
  6.            where name='trig_update_bank'
  7. drop trigger trig_update_bank 
  8. go 
  9.  
  10. create trigger trig_update_bank 
  11. on bank for update  --在bank表上创建update触发器 
  12. as 
  13.    declare @beforeMoney money, 
  14.            @afterMoney  money, 
  15.            @currentTrans money --当前交易金额 
  16.  
  17.    --从deleted临时表,获取交易前的余额 
  18.    select @beforeMoney = currentMoney from deleted; 
  19.    --从inserted临时表,获取交易后的余额 
  20.    select @afterMoney = currentMoney from inserted; 
  21.     
  22.    if abs(@afterMoney-@beforeMoney) > 2000 
  23.       begin 
  24.         print '当前交易金额为:' + 
  25.               convert(varchar(20),abs(@afterMoney-@beforeMoney)) 
  26.         -- 自定义错误消息 
  27.         raiserror('每次交易金额不能超过2000元,交易失败!',16,1) 
  28.         
  29.         rollback transaction --回滚事务,撤销交易! 
  30.         /* 注意: 
  31.            触发器是一个特殊的事务单元 
  32.            不需显示声明begin transaction 
  33.         */ 
  34.       end 
  35. go 
  36.  
  37.  
  38. ------------------ 测试触发器 ------------------ 
  39. set nocount on 
  40.  
  41. --测试1: 在 bank表触发 update触发器 
  42. update bank set currentMoney = currentMoney + 25000 
  43.        where cardID = '1001 0001' 
  44.  
  45. --测试2: 通过 transInfo表的 trig_insert_transInfo触发器 
  46. --             间接触发 bank表的 trig_update_bank触发器 
  47.  
  48. insert into transInfo(cardID,transType,transMoney) 
  49.              values('1001 0001','存入',10000); 
  50.  
  51. --查看结果 
  52. select * from bank 
  53. select * from transInfo 

触发器7_MSDN参考

加密 dml触发器定义

      若要确保其他用户不能查看触发器定义,可以使用with encryption子句加密 dml 触发器。
      使用with encryption子句后,触发器定义即以无法读取的格式进行存储。
      触发器定义加密后,无法进行解密。且任何人都无法进行查看,包括触发器的所有者和系统管理员。

 

update() 函数:

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

使用if update() 子句示例:

 
  1. create table testTable(a int null, b int null
  2.   go 
  3.  
  4.   create trigger my_trig 
  5.   on testTable for insert 
  6.   as 
  7.      if update(b) 
  8.      print '列b已被修改!' 
  9.   go 
  10.   
  11.   insert into testTable(b) values(123); 
  12.  
  13.   -- drop table testTable 

注意:  

      由于 delete 语句无法只对某列进行删除,
      因此不能将if update()子句应用于delete 语句。 

columns_updated() 函数:

也可用于检查 insert或 update语句更新了表中的哪些列。
此函数使用整数位掩码指定要测试的列。

使用columns_updated() 函数示例:

 
  1. create table testTable2(a int null, b int null
  2.   go 
  3.  
  4.   create trigger my_trig2 
  5.   on testTable2 for insert 
  6.   as 
  7.      if ( columns_updated() & 2 = 2 ) 
  8.      print '列b已被修改!' 
  9.   go 
  10.  
  11.   insert into testTable2(b) values(123); 
  12.   
  13.   -- drop table testTable2 

 

 

来自:http://www.cnblogs.com/xugang/archive/2010/02/20/1669619.html