CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
不看会后悔的Windows XP之经验谈 简单快捷DIY实用家庭影院
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  MS-SQL Server >  疑难问题

请高手帮帮忙给讲讲sql中触发器如何使用

楼主maxin0212(手中的沙)2004-04-02 12:59:43 在 MS-SQL Server / 疑难问题 提问

请高手帮帮忙给讲讲sql中触发器如何使用,  
  在什么情况下应用,它跟事务有什么联系吗?  
  能否给写一个实例。 问题点数:0、回复次数:7Top

1 楼zoulipeng(蚂蚁踩死大象)回复于 2004-04-02 20:04:13 得分 0

触发器,满足条件后就自动触发了..Top

2 楼progress99(如履薄冰)回复于 2004-04-02 20:09:34 得分 0

创建触发器,触发器是一种特殊的存储过程,在用户试图对指定的表执行指定的数据修改语句时自动执行。  
          觸發器會隱式啟動事務,故在觸發器中不用顯示使用   begin   tran   ...  
   
  语法  
  CREATE   TRIGGER   trigger_name    
  ON   {   table   |   view   }    
  [   WITH   ENCRYPTION   ]    
  {  
          {   {   FOR   |   AFTER   |   INSTEAD   OF   }   {   [   INSERT   ]   [   ,   ]   [   UPDATE   ]   }  
                  [   WITH   APPEND   ]  
                  [   NOT   FOR   REPLICATION   ]  
                  AS  
                  [   {   IF   UPDATE   (   column   )  
                          [   {   AND   |   OR   }   UPDATE   (   column   )   ]  
                                  [   ...n   ]  
                  |   IF   (   COLUMNS_UPDATED   (   )   {   bitwise_operator   }   updated_bitmask   )  
                                  {   comparison_operator   }   column_bitmask   [   ...n   ]  
                  }   ]    
                  sql_statement   [   ...n   ]    
          }    
  }    
   
   
  Top

3 楼progress99(如履薄冰)回复于 2004-04-02 20:09:48 得分 0

示例  
  A.   使用带有提醒消息的触发器  
  当有人试图在   titles   表中添加或更改数据时,下例将向客户端显示一条消息。  
   
   
   
  说明     消息   50009   是   sysmessages   中的用户定义消息。有关创建用户定义消息的更多信息,请参见   sp_addmessage。    
   
   
  USE   pubs  
  IF   EXISTS   (SELECT   name   FROM   sysobjects  
              WHERE   name   =   'reminder'   AND   type   =   'TR')  
        DROP   TRIGGER   reminder  
  GO  
  CREATE   TRIGGER   reminder  
  ON   titles  
  FOR   INSERT,   UPDATE    
  AS   RAISERROR   (50009,   16,   10)  
  GO  
   
  B.   使用带有提醒电子邮件的触发器  
  当   titles   表更改时,下例将电子邮件发送给指定的人员   (MaryM)。  
   
  USE   pubs  
  IF   EXISTS   (SELECT   name   FROM   sysobjects  
              WHERE   name   =   'reminder'   AND   type   =   'TR')  
        DROP   TRIGGER   reminder  
  GO  
  CREATE   TRIGGER   reminder  
  ON   titles  
  FOR   INSERT,   UPDATE,   DELETE    
  AS  
        EXEC   master..xp_sendmail   'MaryM',    
              'Don''t   forget   to   print   a   report   for   the   distributors.'  
  GO  
   
  C.   在   employee   和   jobs   表之间使用触发器业务规则  
  由于   CHECK   约束只能引用定义了列级或表级约束的列,表间的任何约束(在下例中是指业务规则)都必须定义为触发器。  
   
  下例创建一个触发器,当插入或更新雇员工作级别   (job_lvls)   时,该触发器检查指定雇员的工作级别(由此决定薪水)是否处于为该工作定义的范围内。若要获得适当的范围,必须引用   jobs   表。  
   
  USE   pubs  
  IF   EXISTS   (SELECT   name   FROM   sysobjects  
              WHERE   name   =   'employee_insupd'   AND   type   =   'TR')  
        DROP   TRIGGER   employee_insupd  
  GO  
  CREATE   TRIGGER   employee_insupd  
  ON   employee  
  FOR   INSERT,   UPDATE  
  AS  
  /*   Get   the   range   of   level   for   this   job   type   from   the   jobs   table.   */  
  DECLARE   @min_lvl   tinyint,  
        @max_lvl   tinyint,  
        @emp_lvl   tinyint,  
        @job_id   smallint  
  SELECT   @min_lvl   =   min_lvl,    
        @max_lvl   =   max_lvl,    
        @emp_lvl   =   i.job_lvl,  
        @job_id   =   i.job_id  
  FROM   employee   e   INNER   JOIN   inserted   i   ON   e.emp_id   =   i.emp_id    
        JOIN   jobs   j   ON   j.job_id   =   i.job_id  
  IF   (@job_id   =   1)   and   (@emp_lvl   <>   10)    
  BEGIN  
        RAISERROR   ('Job   id   1   expects   the   default   level   of   10.',   16,   1)  
        ROLLBACK   TRANSACTION  
  END  
  ELSE  
  IF   NOT   (@emp_lvl   BETWEEN   @min_lvl   AND   @max_lvl)  
  BEGIN  
        RAISERROR   ('The   level   for   job_id:%d   should   be   between   %d   and   %d.',  
              16,   1,   @job_id,   @min_lvl,   @max_lvl)  
        ROLLBACK   TRANSACTION  
  END  
   
  D.   使用延迟名称解析  
  下例创建两个触发器以说明延迟名称解析。    
   
  USE   pubs  
  IF   EXISTS   (SELECT   name   FROM   sysobjects  
              WHERE   name   =   'trig1'   AND   type   =   'TR')  
        DROP   TRIGGER   trig1  
  GO  
  --   Creating   a   trigger   on   a   nonexistent   table.  
  CREATE   TRIGGER   trig1  
  on   authors  
  FOR   INSERT,   UPDATE,   DELETE  
  AS    
        SELECT   a.au_lname,   a.au_fname,   x.info    
        FROM   authors   a   INNER   JOIN   does_not_exist   x    
              ON   a.au_id   =   x.au_id  
  GO  
  --   Here   is   the   statement   to   actually   see   the   text   of   the   trigger.  
  SELECT   o.id,   c.text  
  FROM   sysobjects   o   INNER   JOIN   syscomments   c    
        ON   o.id   =   c.id  
  WHERE   o.type   =   'TR'   and   o.name   =   'trig1'  
   
  --   Creating   a   trigger   on   an   existing   table,   but   with   a   nonexistent    
  --   column.  
  USE   pubs  
  IF   EXISTS   (SELECT   name   FROM   sysobjects  
              WHERE   name   =   'trig2'   AND   type   =   'TR')  
        DROP   TRIGGER   trig2  
  GO  
  CREATE   TRIGGER   trig2    
  ON   authors  
  FOR   INSERT,   UPDATE  
  AS    
        DECLARE   @fax   varchar(12)  
        SELECT   @fax   =   phone        
        FROM   authors  
  GO  
  --   Here   is   the   statement   to   actually   see   the   text   of   the   trigger.  
  SELECT   o.id,   c.text  
  FROM   sysobjects   o   INNER   JOIN   syscomments   c    
        ON   o.id   =   c.id  
  WHERE   o.type   =   'TR'   and   o.name   =   'trig2'  
   
  E.   使用   COLUMNS_UPDATED  
  下例创建两个表:一个   employeeData   表和一个   auditEmployeeData   表。人力资源部的成员可以修改   employeeData   表,该表包含敏感的雇员薪水信息。如果更改了雇员的社会保险号码   (SSN)、年薪或银行帐户,则生成审核记录并插入到   auditEmployeeData   审核表。  
   
  通过使用   COLUMNS_UPDATED()   功能,可以快速测试对这些包含敏感雇员信息的列所做的更改。只有在试图检测对表中的前   8   列所做的更改时,COLUMNS_UPDATED()   才起作用。  
   
  USE   pubs  
  IF   EXISTS(SELECT   TABLE_NAME   FROM   INFORMATION_SCHEMA.TABLES  
        WHERE   TABLE_NAME   =   'employeeData')  
        DROP   TABLE   employeeData  
  IF   EXISTS(SELECT   TABLE_NAME   FROM   INFORMATION_SCHEMA.TABLES  
        WHERE   TABLE_NAME   =   'auditEmployeeData')  
        DROP   TABLE   auditEmployeeData  
  GO  
  CREATE   TABLE   employeeData   (  
        emp_id   int   NOT   NULL,  
        emp_bankAccountNumber   char   (10)   NOT   NULL,  
        emp_salary   int   NOT   NULL,  
        emp_SSN   char   (11)   NOT   NULL,  
        emp_lname   nchar   (32)   NOT   NULL,  
        emp_fname   nchar   (32)   NOT   NULL,  
        emp_manager   int   NOT   NULL  
        )  
  GO  
  CREATE   TABLE   auditEmployeeData   (  
        audit_log_id   uniqueidentifier   DEFAULT   NEWID(),  
        audit_log_type   char   (3)   NOT   NULL,  
        audit_emp_id   int   NOT   NULL,  
        audit_emp_bankAccountNumber   char   (10)   NULL,  
        audit_emp_salary   int   NULL,  
        audit_emp_SSN   char   (11)   NULL,  
        audit_user   sysname   DEFAULT   SUSER_SNAME(),  
        audit_changed   datetime   DEFAULT   GETDATE()  
        )  
  GO  
  CREATE   TRIGGER   updEmployeeData    
  ON   employeeData    
  FOR   update   AS  
  /*Check   whether   columns   2,   3   or   4   has   been   updated.   If   any   or   all   of   columns   2,   3   or   4   have   been   changed,   create   an   audit   record.   The   bitmask   is:   power(2,(2-1))+power(2,(3-1))+power(2,(4-1))   =   14.   To   check   if   all   columns   2,   3,   and   4   are   updated,   use   =   14   in   place   of   >0   (below).*/  
   
        IF   (COLUMNS_UPDATED()   &   14)   >   0  
  /*Use   IF   (COLUMNS_UPDATED()   &   14)   =   14   to   see   if   all   of   columns   2,   3,   and   4   are   updated.*/  
              BEGIN  
  --   Audit   OLD   record.  
              INSERT   INTO   auditEmployeeData  
                    (audit_log_type,  
                    audit_emp_id,  
                    audit_emp_bankAccountNumber,  
                    audit_emp_salary,  
                    audit_emp_SSN)  
                    SELECT   'OLD',    
                          del.emp_id,  
                          del.emp_bankAccountNumber,  
                          del.emp_salary,  
                          del.emp_SSN  
                    FROM   deleted   del  
   
  --   Audit   NEW   record.  
              INSERT   INTO   auditEmployeeData  
                    (audit_log_type,  
                    audit_emp_id,  
                    audit_emp_bankAccountNumber,  
                    audit_emp_salary,  
                    audit_emp_SSN)  
                    SELECT   'NEW',  
                          ins.emp_id,  
                          ins.emp_bankAccountNumber,  
                          ins.emp_salary,  
                          ins.emp_SSN  
                    FROM   inserted   ins  
        END  
  GO  
   
  /*Inserting   a   new   employee   does   not   cause   the   UPDATE   trigger   to   fire.*/  
  INSERT   INTO   employeeData  
        VALUES   (   101,   'USA-987-01',   23000,   'R-M53550M',   N'Mendel',   N'Roland',   32)  
  GO  
   
  /*Updating   the   employee   record   for   employee   number   101   to   change   the   salary   to   51000   causes   the   UPDATE   trigger   to   fire   and   an   audit   trail   to   be   produced.*/  
   
  UPDATE   employeeData  
        SET   emp_salary   =   51000  
        WHERE   emp_id   =   101  
  GO  
  SELECT   *   FROM   auditEmployeeData  
  GO  
   
  /*Updating   the   employee   record   for   employee   number   101   to   change   both   the   bank   account   number   and   social   security   number   (SSN)   causes   the   UPDATE   trigger   to   fire   and   an   audit   trail   to   be   produced.*/  
   
  UPDATE   employeeData  
        SET   emp_bankAccountNumber   =   '133146A0',   emp_SSN   =   'R-M53550M'  
        WHERE   emp_id   =   101  
  GO  
  SELECT   *   FROM   auditEmployeeData  
  GO  
   
  F.   使用   COLUMNS_UPDATED   测试   8   列以上  
  如果必须测试影响到表中前   8   列以外的列的更新时,必须使用   UBSTRING   函数测试由   COLUMNS_UPDATED   返回的适当的位。下例测试影响   Northwind.dbo.Customers   表中的第   3、第   5   或第   9   列的更新。  
   
  USE   Northwind  
  DROP   TRIGGER     tr1  
  GO  
  CREATE   TRIGGER   tr1   ON   Customers  
  FOR   UPDATE   AS  
        IF   (   (SUBSTRING(COLUMNS_UPDATED(),1,1)=power(2,(3-1))  
              +   power(2,(5-1)))    
              AND   (SUBSTRING(COLUMNS_UPDATED(),2,1)=power(2,(1-1)))  
              )    
        PRINT   'Columns   3,   5   and   9   updated'  
  GO  
   
  UPDATE   Customers    
        SET   ContactName=ContactName,  
              Address=Address,  
              Country=Country  
  GO  
   
  Top

4 楼progress99(如履薄冰)回复于 2004-04-02 20:10:28 得分 0

以上過程可在   pubs數據庫中測試。Top

5 楼quansui(叶子)回复于 2004-04-03 01:46:40 得分 0

学习Top

6 楼maxin0212(手中的沙)回复于 2004-04-03 10:16:33 得分 0

谢谢楼上的!upTop

7 楼yongyupost2000(阿鱼)回复于 2004-04-05 17:16:54 得分 0

触发器的优点如下:    
   
  触发器可通过数据库中的相关表实现级联更改;不过,通过级联引用完整性约束可以更有效地执行这些更改。  
   
   
  触发器可以强制比用   CHECK   约束定义的约束更为复杂的约束。    
  与   CHECK   约束不同,触发器可以引用其它表中的列。例如,触发器可以使用另一个表中的   SELECT   比较插入或更新的数据,以及执行其它操作,如修改数据或显示用户定义错误信息。  
   
  触发器也可以评估数据修改前后的表状态,并根据其差异采取对策。  
   
   
  一个表中的多个同类触发器(INSERT、UPDATE   或   DELETE)允许采取多个不同的对策以响应同一个修改语句。    
  Top

相关问题

  • sql中的触发器如何使用?
  • Delphi+sql server 在使用触发器应该注意什么
  • sql server触发器问题
  • SQL SERVER触发器问题?
  • sql触发器小问题
  • 关于SQL Server触发器
  • Sql Server7.0触发器问题
  • 求助sql server2000 触发器
  • SQL触发器求助
  • sql server 触发器问题

关键词

  • 触发器
  • audit
  • emp
  • lvl
  • trigger
  • 表
  • bankaccountnumber
  • employeedata
  • trig
  • auditemployeedata

得分解答快速导航

  • 帖主:maxin0212

相关链接

  • SQL Server类图书

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
北京创新乐知广告有限公司 版权所有, 京 ICP 证 070598 号
世纪乐知(北京)网络技术有限公司 提供技术支持
Copyright © 2000-2008, CSDN.NET, All Rights Reserved
GongshangLogo