--浅析触发器
1、关于inserted 表和deleted 表
触发器语句中使用了两种特殊的表:inserted 表和deleted 表
inserted 表放的是本次insert操作插入的数据或本次update操作更新后的数据。
deleted  表放的是本次delete操作删除的数据或本次update操作更新前的数据。
2、inserted 表和deleted 表里的记录数。
该记录数取决于是批量插入还是单条插入。
如:
insert tb select 1 union select 2 union select 3 union select 4
--以上就属于批量插入,只触发一次insert触发器,但是inserted里面同时有4条数据。
insert tb select 1 
insert tb select 2 
insert tb select 3 
insert tb select 4 
--以上属于单条插入,每插入一条触发一次insert触发器,每次触发器里只有一条数据。
3、这个也很重要
将触发器里的语句和触发它的语句作为可在触发器内回滚的单个事务对待。
也就是说,向表插入数据成功了,但是触发器的操作报错了,那么整个事务是回滚的,即
本表数据插入回滚,触发器里的语句操作回滚。
如果在触发器里回滚触发器里的SQL,且不影响原有的操作,建议用
set xact_abort off 选项。
4、关于 for 触发器和 instead of 触发器。
for 等同于 after,也就是在insert、delete或update之后,才执行触发器里的语句。
instead of 等同于代替insert、delete或update操作。虽然,这时候inserted或deleted两个特殊
表里有数据,但是并没有对本表数据进行insert、delete或update操作,这样的话,你还要在触发
器里手工进行对本表insert、delete或update的操作。
5、if update(colname)
大家注意哦,这个不只会在update触发器里用到,INSERT触发器里也会用到的。以下是说明:
对特定列的更改进行测试
触发器定义中的 IF UPDATE (列名)子句可用来确定 INSERT 或 UPDATE 语句是否影响到表中的一个特定列。
无论何时,当列被赋值时,该子句即为 TRUE。
还有:
IF COLUMNS_UPDATED() 子句检查表中已用 INSERT 或 UPDATE 语句更新的列。该子句使用整型位掩码指定需测试的列








简介

  触发器可以查询其他表,而且可以包含复杂的

SQL 语句。它们主要用于强制服从复杂的业务规则或要求。例如:您可以根据客户当前的帐户状态,控制是否允许插入新订单。


  触发器也可用于强制引用完整性,以便在多个表中添加、更新或删除行时,保留在这些表之间所定义的关系。然而,强制引用完整性的最好方法是在相关表中定义主键和外键约束。如果使用数据库关系图,则可以在表之间创建关系以自动创建外键约束。


创建触发器的SQL语法

  DELIMITER |


  CREATE TRIGGER `<databaseName>`.`<triggerName>`


  < [ BEFORE | AFTER ] > < [ INSERT | UPDATE | DELETE ] >


  ON <tableName>


  FOR EACH ROW


  BEGIN


  --do something


  END |


触发器的优点

 


 触发器可通过数据库中的相关表实现级联更改;不过,通过级联引用完整性约束可以更有效地执行这些更改。触发器可以强制比用 CHECK


约束定义的约束更为复杂的约束。与 CHECK 约束不同,触发器可以引用其它表中的列。例如,触发器可以使用另一个表中的 SELECT


比较插入或更新的数据,以及执行其它操作,如修改数据或显示用户定义错误信息。触发器也可以评估数据修改前后的表状态,并根据其差异采取对策。一个表中的


多个同类触发器(INSERT、UPDATE 或 DELETE)允许采取多个不同的对策以响应同一个修改语句。


比较触发器与约束

 


 约束和触发器在特殊情况下各有优势。触发器的主要好处在于它们可以包含使用 Transact-SQL


代码的复杂处理逻辑。因此,触发器可以支持约束的所有功能;但它在所给出的功能上并不总是最好的方法。实体完整性总应在最低级别上通过索引进行强制,这些


索引或是 PRIMARY KEY 和 UNIQUE 约束的一部分,或是在约束之外独立创建的。假设功能可以满足应用程序的功能需求,域完整性应通过


CHECK 约束进行强制,而引用完整性 (RI) 则应通过 FOREIGN KEY


约束进行强制。在约束所支持的功能无法满足应用程序的功能要求时,触发器就极为有用。


  例如:除非 REFERENCES 子句定义了级联引用操作,否则 FOREIGN KEY 约束只能以与另一列中的值完全匹配的值来验证列值。


  CHECK 约束只能根据逻辑表达式或同一表中的另一列来验证列值。如果应用程序要求根据另一个表中的列验证列值,则必须使用触发器。


  约束只能通过标准的系统错误信息传递错误信息。如果应用程序要求使用(或能从中获益)自定义信息和较为复杂的错误处理,则必须使用触发器。


  触发器可通过数据库中的相关表实现级联更改;不过,通过级联引用完整性约束可以更有效地执行这些更改。


  触发器可以禁止或回滚违反引用完整性的更改,从而取消所尝试的数据修改。当更改外键且新值与主


键不匹配时,此类触发器就可能发生作用。例如,可以在 titleauthor.title_id 上创建一个插入触发器,使它在新值与


titles.title_id 中的某个值不匹配时回滚一个插入。不过,通常使用 FOREIGN KEY 来达到这个目的。


  如果触发器表上存在约束,则在 INSTEAD OF 触发器执行后但在 AFTER 触发器执行前检查这些约束。如果约束破坏,则回滚 INSTEAD OF 触发器操作并且不执行 AFTER 触发器。


  触发器到底可不可以在视图上创建 在 SQL Server™ 联机丛书中,是没有说触发器不能在视图上创建的, 并且在语法解释中表明:


  在 CREATE TRIGGER 的 ON 之后可以是视图。


然而,事实似乎并不是如此,很多专家也说触发器不能在视图上创建。我也专门作了测试,的确如此,不管是普通视图还是索引视图,都无法在上面创建触发器,真


的是这样吗?请点击详细,但是无可厚非的是:当在临时表或系统表上创建触发器时会遭到拒绝。 深刻理解 FOR CREATE TRIGGER 语句的


FOR 关键字之后可以跟 INSERT、UPDATE、DELETE 中的一个或多个,也就是说在其它情况下是不会触发触发器的, 包括


SELECT、TRUNCATE、WRITETEXT、UPDATETEXT。相关内容


一个有趣的应用我们看到许多注册系统在注册后都不能更改用户名,但这多半是由应用程序决定的, 如果直接打开数据库表进行更改,同样可以更改其用户名,


在触发器中利用回滚就可以巧妙地实现无法更改用户名……详细内容 触发器内部语句出错时……


这种情况下,前面对数据更改操作将会无效。举个例子,在表中插入数据时触发触发器,而触发器内部此时发生了运行时错误,那么将返回一个错误值,并且拒绝刚


才的数据插入。不能在触发器中使用的语句 触发器中可以使用大多数 T-SQL 语句,但如下一些语句是不能在触发器中使用的。


  CREATE 语句,如:CREATE DATABASE、CREATE TABLE、CREATE INDEX 等。


  ALTER 语句,如:ALTER DATABASE、ALTER TABLE、ALTER INDEX 等。


  DROP 语句,如:DROP DATABASE、DROP TABLE、DROP INDEX 等。


  DISK 语句,如:DISK INIT、DISK RESIZE。


  LOAD 语句,如:LOAD DATABASE、LOAD LOG。


  RESTORE 语句,如:RESTORE DATABASE、RESTORE LOG。


  RECONFIGURE


  TRUNCATE TABLE 语句在sybase的触发器中不可使用!


慎用触发器

  触发器功能强大,轻松可靠地实现许多复杂的功能,为什么又要慎用呢。触发器本身没有过错,但由于我们的滥用会造成数据库及应用程序的维护困难。在数据库操作中,我们可以通过关系、触发器、存储过程、应用程序等来实现数据操作…… 同时规则、约束、

缺省值也是保证

数据完整性的重要保障。如果我们对触发器过分的依赖,势必影响数据库的结构,同时增加了维护的复杂程序.







sqlserver触发器  






一﹕ 触发器是一种特殊的存储过程﹐它不能被显式地调用﹐而是在往表中插入记录﹑更新记录或者删除记录时被自动地激活。所以触发器可以用来实现对表实施复杂的完整性约`束。
         
二﹕ SQL Server为每个触发器都创建了两个专用表﹕Inserted表和Deleted表。这两个表由系统来维护﹐它们存在于内存中而不是在数据库中。这两个表的结构总是与被该触发器作用的表的结构相同。触发器执行 完成后﹐与该触发器相关的这两个表也被删除。
Deleted表存放由于执行Delete或Update语句而要从表中删除的所有行。
Inserted表存放由于执行Insert或Update语句而要向表中插入的所有行。
三﹕Instead of 和 After触发器
SQL Server2000提供了两种触发器﹕Instead of 和After 触发器。这两种触发器的差别在于他们被激活的同﹕
        
Instead of触发器用于替代引起触发器执行的T-SQL语句。除表之外﹐Instead of 触发器也可以用于视图﹐用来扩展视图可以支持的更新操作。
        
After触发器在一个Insert,Update或Deleted语句之后执行﹐进行约束检查等动作都在After触发器被激活之前发生。After触发器只能用于表。
        
一个表或视图的每一个修改动作(insert,update和delete)都可以有一个instead of 触发器﹐一个表的每个修改动作都可以有多个After触发器。
四﹕触发器的执行过程
如果一个Insert﹑update或者delete语句违反了约束﹐那幺After触发器不会执行﹐因为对约束的检查是在After触发器被激动之前发生的。所以After触发器不能超越约束。
       
Instead of 触发器可以取代激发它的操作来执行。它在Inserted表和Deleted表刚刚建立﹐其它任何操作还没有发生时被执行。因为Instead of 触发器在约束之前执行﹐所以它可以对约束进行一些预处理。
        
五﹕使用T-SQL语句来创建触发器
  
基本语句如下﹕        
           create trigger trigger_name
           on {table_name | view_name}
           {for | After | Instead of }
           [ insert, update,delete ]
           as
           sql_statement
          
六﹕相关示例﹕         
1﹕在Orders表中建立触发器﹐当向Orders表中插入一条订单记录时﹐检查goods表的货品状态status是否为1(正在整理)﹐是﹐则不能往Orders表加入该订单。
create trigger orderinsert
on orders
after insert
as



begin transaction
if (select status from goods,inserted
where goods.name=inserted.goodsname)=1
begin
print 'the goods is being processed'
print 'the order cannot be committed'
rollback transaction   --回滚﹐避免加入
end
2﹕在Orders表建立一个插入触发器﹐在添加一条订单时﹐减少Goods表相应的货品记录中的库存。
create trigger orderinsert1
on orders
after insert
as



begin transaction
update goods set storage=storage-inserted.quantity
from goods,inserted
where
goods.name=inserted.goodsname
3﹕在Goods表建立删除触发器﹐实现Goods表和Orders表的级联删除。
create trigger goodsdelete
on goods
after delete
as



begin transaction
delete from orders
where goodsname in
(select name from deleted)
4﹕在Orders表建立一个更新触发器﹐监视Orders表的订单日期(OrderDate)列﹐使其不能手工修改.
create trigger orderdateupdate
on orders
after update
as



begin transaction
if update(orderdate)
begin
raiserror(' orderdate cannot be modified',10,1)
rollback transaction
end
5﹕在Orders表建立一个插入触发器﹐保证向Orders表插入的货品名必须要在Goods表中一定存在。
create trigger orderinsert3
on orders
after insert
as



begin transaction
if (select count(*) from goods,inserted where goods.name=inserted.goodsname)=0
begin
print ' no entry in goods for this order'
rollback transaction
end






触发器的基础知识和例子

:create trigger tr_name
   on table/view
{for | after | instead of } [update][,][insert][,][delete]
[with encryption]
as {batch | if update (col_name) [{and|or} update (col_name)] }
说明:1  tr_name :触发器名称
2 on table/view :触发器所作用的表。一个触发器只能作用于一个表
3 for 和after :同义
4 after 与instead of :sql 2000新增项目

after 与 instead of 的区别
After                     Instead of
在触发事件发生以后才被激活   代替了相应的触发事件而被执行
只可以建立在表上            既可以建立在表上也可以建立在视图上
5 insert、update、delete:激活触发器的三种操作,可以同时执行,也可选其一
6 if update (col_name):表明所作的操作对指定列是否有影响,有影响,则激活触发器。此外,因为delete 操作只对行有影响,所以如果使用delete
操作就不能用这条语句了(虽然使用也不出错,但是不能激活触发器,没意义)。
7 触发器执行时用到的两个特殊表:deleted ,inserted
  deleted 和inserted 可以说是一种特殊的临时表,是在进行激活触发器时由系统自动生成的,其结构与触发器作用的表结构是一样的,只是存放 的数据有差异。


下面表格说明deleted 与inserted 数据的差异
deleted 与inserted 数据的差异
Inserted                            | Deleted
存放进行insert和update 操作后的数据 |存放进行delete 和update操作前的
                                     数据
注意:update 操作相当于先进行delete 再进行insert ,所以在进行update操作时,修改前的数据拷贝一条到deleted 表中,修改后的数据在存到触发器作用的表的同时,也同时生成一条拷贝到insered表中

use pubs
go
BEGIN TRAN
create table table1(列1 int,列2 int)
create table table2(列11 int,列22 int)
go

CREATE TRIGGER t_dalii ON table1
AFTER INSERT
----^^^^^^当插入时触发
AS
begin
  SELECT * FROM TABLE2;
  insert table2 select * from inserted
-------------------------------^^^^^^^^^存放插入临时数据的临时表
end
go

----------**你向table1插入数据时table2也会插入同样的数据**--
insert table1 values(1,2)
select * from table1
select * from table2
drop table table1
drop table table2
COMMIT TRAN