定义

在SQL Server里面也就是对某一个表的一定的操作,触发某种条件,从而执行的一段程序。触发器是一个特殊的存储过程。

常见的触发器有三种:分别应用于Insert , Update , Delete 事件。

我们为什么要使用触发器, 比如:

1.当我们修改了一张表, 需要在日志中记录一下,这样就需要用到触发器(不知道大家是不是用的其他方法)

2.虚拟采购表和库存表, 当采购表inert了一条数据, 相应的要在库存表中update或insert一条数据

3.虚拟销售表和库存表, 当销售表inert了一条数据, 相应的要在库存表中update一条数据

例1

create trigger myTrigger --创建触发器
on tb--触发源
for updateas --触发操作
insert into Sys_Log values (........)--触发结果
 

触发器语句中使用了两种特殊的表:deleted 表和 inserted 表。

Deleted 表用于存储 DELETE 和 UPDATE 语句所影响的行的复本。在执行 DELETE 或 UPDATE 语句时,行从触发器表中删除,并传输到 deleted 表中。Deleted 表和触发器表通常没有相同的行。

Inserted 表用于存储 INSERT 和 UPDATE 语句所影响的行的副本。在一个插入或更新事务处理中,新建行被同时添加到 inserted 表和触发器表中。Inserted 表中的行是触发器表中新行的副本。

1.插入操作(Insert)

Inserted表有数据,Deleted表无数据

2.删除操作(Delete)

Inserted表无数据,Deleted表有数据

3.更新操作(Update)

Inserted表有数据(新数据),Deleted表有数据(旧数据)

 

例2

CREATE TRIGGER T_INSERT_卷烟销售表 
ON 卷烟销售表 
FOR INSERT 
AS 
BEGIN TRANSACTION 
------------------------------------------------------
--检查数据的合法性:销售的卷烟是否有库存,或者库存是否大于零 
IF NOT EXISTS ( 
SELECT 库存数量 
FROM 卷烟库存表 
WHERE 卷烟品牌 IN (SELECT 卷烟品牌 FROM INSERTED) 
) 
BEGIN 
--返回错误提示 
RAISERROR(’错误!该卷烟不存在库存,不能销售。’,16,1) 
--回滚事务 
ROLLBACK 
RETURN 
END 
------------------------------------------------------
IF EXISTS ( 
SELECT 库存数量 
FROM 卷烟库存表 
WHERE 卷烟品牌 IN (SELECT 卷烟品牌 FROM INSERTED) AND 
库存数量 <= 0 
) 
BEGIN 
--返回错误提示 
RAISERROR(’错误!该卷烟库存小于等于0,不能销售。’,16,1) 
--回滚事务 
ROLLBACK 
RETURN 
END 
 
 
-------------对合法的数据进行处理 --------------------
 
--强制执行下列语句,保证业务规则 
UPDATE 卷烟销售表 
SET 销售金额 = 销售数量 * 销售单价 
WHERE 卷烟品牌 IN (SELECT 卷烟品牌 FROM INSERTED) 
 
DECLARE @卷烟品牌 VARCHAR(40) 
SET @卷烟品牌 = (SELECT 卷烟品牌 FROM INSERTED) 
 
DECLARE @销售数量 MONEY 
SET @销售数量 = (SELECT 销售数量 FROM INSERTED) 
 
UPDATE 卷烟库存表 
SET 库存数量 = 库存数量 - @销售数量, 
库存金额 = (库存数量 - @销售数量)*库存单价 
WHERE 卷烟品牌 = @卷烟品牌 
COMMIT TRANSACTION 
GO 

 

补充:

1、本示例主要通过一个简单的业务规则实现来进行触发器使用的说明,具体的要根据需要灵活处理;

2、关于触发器要理解并运用好 INSERTED ,DELETED 两个系统表;

3、本示例创建的触发器都是 FOR INSERT ,具体的语法可参考:

 

Trigger语法

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 ] 
} 
} 

☑ if update (col_name):表明所作的操作对指定列是否有影响,有影响,则激活触发器。此外,因为delete 操作只对行有影响, 所以如果使用delete操作就不能用这条语句了(虽然使用也不出错,但是不能激活触发器,没意义)。

☑ 触发器执行时用到的两个特殊表:deleted ,inserted deleted 和inserted 可以说是一种特殊的临时表,是在进行激活触发器时由系统自动生成的,其结构与触发器作用的表结构是一

样的,只是存放 的数据有差异。

 

在sql触发器中如何获得被修改行的ID

这个在上面的例2中已经有所提及

create trigger TgName
on tb
for update
as
if update(recommend)
begin
update tb set commenddate=(getdate()) from tb inner join inserted on tb.vlistid=Inserted.vlistid
end

关键在于Inserted


触发器貌似代替了之前我在BLL写事务来处理原子性操作的代码, 应该是一种简化.

更详细内容参看http://wenku.baidu.com/view/3b3fb53343323968011c92ce.html