什么是SQL触发器

时间:2021-07-11 05:04:05

在SQL中,触发器是一种特殊类型的存储过程,它不同于SQL的存储过程。触发器主要是通过事件进行触发而被执行的,而存储过程可以通过存储过程名字而被直接调用。当对某一表进行诸如UPDATE、 INSERT、 DELETE 这些操作时,SQL Server 就会自动执行触发器所定义的SQL 语句,从而确保对数据的处理必须符合由这些SQL 语句所定义的规则。

 

触发器的种类

SQL Server 2000 支持两种类型的触发器:AFTER 触发器和INSTEAD OF 触发器。其中AFTER 触发器即为SQL Server 2000 版本以前所介绍的触发器。该类型触发器要求只有执行某一操作(INSERT UPDATE DELETE) 之后,触发器才被触发,且只能在表上定义。可以为针对表的同一操作定义多个触发器。对于AFTER 触发器,可以定义哪一个触发器被最先触发,哪一个被最后触发,通常使用系统过程sp_settriggerorder 来完成此任务。

INSTEAD OF 触发器表示并不执行其所定义的操作(INSERT、 UPDATE、 DELETE),而仅是执行触发器本身。既可在表上定义INSTEAD OF 触发器,也可以在视图上定义INSTEAD OF 触发器,但对同一操作只能定义一个INSTEAD OF触发器。

 

 

当某读者还书时,能按照读者的类别判断他是否超过借书期限,超过则罚款:一天3角,自动将罚款金额进行计算,填入对应的属性里。

    CREATE TRIGGER books_rt_upd
ON books_rt
FOR UPDATE
AS
IF UPDATE (return_date)
BEGIN

-- 定义 借书日期
declare @lend_date date
-- 定义 应还书日期
declare @return_date date
-- 定义 超出天数
declare @exday int
-- 定义 超出价格
declare @exfee decimal
-- 定义 用户id
declare @userid
-- 定义 用户id
declare @usertype


-- 修改用户归还日期,和借书的id号

select @return_date=return_date , @lendid = lendid from INSERTED

select
@lend_date=lend_date,@userid=userid ,@usertype=@usertype
from
books_rt
where lendid in (select lendid from INSERTED)



-- 计算超出多少天并乘以价格
set @exday = @return_date - @lend_date

-- 根据用户级别察看是否超过天数
IF @usertype= '01' begin
if @exday > '10' --01级别可以借书10天
begin
set @exday = @exday - 10
end
end

IF @usertype= '02' begin
if @exday > '20' --02级别可以借书20天
begin
set @exday = @exday - 20
end
end

set @exfee = @exday * 0.3

-- 修改用户帐户表
update user_account set user_fee = userfee - @exfee
where userid = @userid


END

 

 

 

 

 

 

 

 

 

 

 

 

先简单说说触发器的机制。每个触发器都会创建两个逻辑专用表:inserted表和deleted表,其结构跟被触发表的结构完全相同,执行后,这两个表都会被删除。执行insert插入语句时,inserted表存放要插入的所有行,执行delete删除操作时,deleted表存放要删除的所有行,执行update更新操作相当于先执行一个delete操作再执行有个insert操作,原记录存放于deleted表新记录存放于inserted表。

触发器分after触发器和instead of触发器两种。

After触发器也叫For触发器,它会在触发insert、update或delete动作之后执行,也即它只有在已插入一行或是多行和所有约束已被处理且通过后才触发,并且AFTER 触发器只能对表起作用。

instead of触发器代替触发动作进行激发,如果一个表上有一个instead of触发器并在这个表上执行update操作,则update语句不会改变这个表中的数据。INSTEAD
OF 触发器可以同时对表和视图起作用。

AFTER 触发器多用在动作必须在表中数据发生改变之后才执行后情情况,比如,AFTER 触发器可以用于将对数据作任何变动的日志记录在一个相对独立的审计表中。INTEAD
OF 触发器也能做同样的工作。但是 INSTEAD OF 触发器在这个情况下的效率比较低,因为更新动作只能在将它发生的动作准确地记录在审计表之后才允许执行。一般来说,只要不影响数据的修改,AFTER 触发器比 INSTEAD OF 触发器更有效率,但有时 INSTEAD OF会更好些。

理论是枯燥的,对于初学者而言也是难懂的,通过一些实例会更有利于理解和消化。

1、更新触发

create trigger updateUser

on allUser

after
update

as

update partUser

set usr_Name=(select usr_Name from inserted), usr_Pwd=(select usr_pwd from inserted)

where usr_ID=(select usr_id from inserted)





2、不允许修改用户名

use 数据库名
go
create trigger tr
on 表名
for update
as
   
if update(userName)
       
rollback tran
--INSTEAD OF 触发器
CREATE TRIGGER [checkid] ON [dbo].[计0261]
INSTEAD
OF insert
AS
IF NOT EXISTS(SELECT * FROM 计026 WHERE 学号=(SELECT 学号 FROM INSERTED))
 
BEGIN
   
ROLLBACK TRANSACTION
   
PRINT '要处理记录的学号不存在!'
 
END
ELSE
 
BEGIN
   
INSERT INTO 计0261 select * from inserted
   
PRINT '已经成功处理记录!'
 
END
go
--AFTER(FOR)触发器
CREATE TRIGGER [orderinsert] ON [dbo].[订货表]
AFTER
INSERT
AS
DECLARE @bookid int, @ordernum int, @num int
SELECT @bookid = 书籍编号, @ordernum = 数量 FROM INSERTED
SELECT @num = count(书籍编号) FROM 订货统计表 WHERE 书籍编号=@bookid
IF @num = 0
 
--未找到该书,插入记录
  INSERT INTO 订货统计表 VALUES(@bookid, @ordernum)
ELSE
 
--找到该书,更新记录
  UPDATE 订货统计表
SET 总订货量 = 总订货量 + @ordernum WHERE 书籍编号 = @bookid