博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SQL_Server_2008完全学习之第十章触发器
阅读量:5308 次
发布时间:2019-06-14

本文共 4685 字,大约阅读时间需要 15 分钟。

-

1、什么时触发器?

 

1)触发器是一个在修改指定表中的数据时执行的存储过程。经常通过创建触发器来强制实现不同表中的逻辑相关数据的引用完整性或一致性。由于用户不能绕过触发器,所以可以用它来强制实施复杂的业务规则,以此确保数据的完整性。

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

 

为什么要使用触发器?

1)触发器自动执行,它们在表的数据作了任何修改(比如手工输入或者使用程序采集的操作)之后立即激活。

2)触发器可以通过数据库中的相关表进行层叠更改。这比直接把代码写在前台的做法更完全合理。

3)触发器可以强制限制,这些限制比用CHECK约束所定义的更复杂。与CHECK约束不同的是,触发器可以引用其他表中的列。

 

触发器的种类

 

1)DDL触发器

DDL触发器当服务器或者数据库中发生数据定义语言(DDL)事件时被调用。如果要执行以下操作,可以使用DDL触发器:

a)要防止对数据库架构进行某些更改

b)希望数据库中发生某种情总以响应数据库架构中的更改

c)要记录数据库架构中的更改或者事件

2)DML触发器

DML触发器是当数据库服务器发生数据操作语言(DML)事件时要执行的操作。通常所说的DML触发器主要包括三种:INSERT触发器、UPDATE触发器、DELETE触发器。DML触发器可以查询其他表,还可以包含复杂的T-SQL语句。将触发器和触发它的语句做为可在触发器内回滚的单个事务对待。如果检测到错误,则整个事务自动回滚。

 

2、创建INSERT触发器

 

语法格式

CREATE TRIGGER trigger_name

ON {table|view}

{

{

{FOR | AFTER | INSTEAD OF}

{[DELETE][,][INSERT][,][UPDATE]}

AS

sql _statement

}

}

 

--
创建订单时,减少相应产品的库存数量
CREATE 
TRIGGER t_AddOrder
on 
[
ORDER
]
for 
insert
as 
declare 
@pid 
int
@sale 
int
select 
@pid
=pid,
@sale
=
[
count
] 
from inserted
update product 
set proCount
=proCount
-
@sale 
where PID 
= 
@pid

 

3、创建DELETE触发器

 

--
删除订单时,减少相应产品的库存数量
ALTER 
TRIGGER t_RemoveOrder
on 
[
ORDER
]
for 
delete
as 
DECLARE cur_deleted scroll 
CURSOR 
FOR 
select pid,
[
count
] 
from deleted
FOR 
read 
only
OPEN cur_deleted
declare 
@pid 
int
@sale 
int
FETCH 
NEXT 
FROM cur_deleted 
into 
@pid,
@sale
while 
@@fetch_status
=
0
BEGIN
    
update product 
set proCount
=proCount
+
@sale 
where PID 
= 
@pid
    
FETCH 
NEXT 
FROM cur_deleted 
into 
@pid,
@sale
End
CLOSE cur_deleted
DEALLOCATE cur_deleted
insert 
into 
[
Order
] (pid,
[
count
]
values (
1,
2)
insert 
into 
[
Order
] (pid,
[
count
]
values (
2,
3)
delete 
[
Order
]
select 
* 
from 
[
Order
]
select 
* 
from 
[
Product
]

 

4、创建UPDATE触发器

 

注:可以把UPDATE动作看作DELETE + INSERT 动作的组合,既先删除旧的这些记录,再插入一条新的记录,此时在数据库中存在了两个临时表,既是DELETED和INSERTD。

 

--
使用UPDATE触发器给列加上修改权限
CREATE 
TRIGGER t_EditProduct
ON 
[
Product
] 
For 
Update
as
if 
update(proName)
BEGIN
    
print 
'
产品名称为基础数据,不能被修改!
'
    
--
回滚事务
    
ROLLBACK 
Transaction
END
else
BEGIN
    
print 
'
修改成功!
';
END
--
执行失败
UPDATE Product 
set proName
=
'
IPhone 4
' 
where pid 
= 
1
--
执行成功
UPDATE Product 
set proCount
=
10 
where pid 
= 
1

 

5、创建DDL触发器

 

语法格式

CREATE TRIGGER trigger_name

ON {ALL SERVER|DATABASE}

WITH ENCRYPTIION

FOR|AFTER|{event_type}

AS

sql_statement

 

--
使用DDL触发器禁止删除或修改表
CREATE 
trigger t_DontDeleteTables
ON 
Database
For Drop_table,Alter_table
AS
Begin
    
print 
'
系统禁止删除或修改表!
';
    
Rollback 
Transaction
End
DROP 
table 
[
Order
]

 

6、管理触发器

 

--
删除触发器
drop 
trigger trigger_name
--
禁用触发器
disable 
trigger trigger_name
--
启用触发器
enable 
trigger trigger_name
--
示例
ALTER 
table 
[
Order
] 
add status 
int 
not 
null 
default 
0
--
禁用指定触发器
disable 
trigger t_DontDeleteTables

 

7、嵌套触发器(最多32层)

 

 

--
嵌套触发器完整示例
CREATE 
TABLE Department(
departmentId 
int 
not 
null 
identity(
1,
1
primary 
key,
departmentName 
nvarchar(
20
not 
null,
departmentCount 
int 
not 
null 
default 
0
)
CREATE 
TABLE Personnel(
personnelId 
int 
not 
null 
identity(
1,
1
primary 
key,
departmentId 
int 
not 
null,
personnelName 
nvarchar(
10
not 
null
)
CREATE 
TABLE NewPersonnel
(
personnelId 
int 
not 
null 
identity(
1,
1
primary 
key,
departmentId 
int 
not 
null,
personnelName 
nvarchar(
10
not 
null
)
insert 
into Department (departmentName) 
values (
'
总经办
'),(
'
财务部
'),(
'
行政人事部
'),(
'
信息技术部
'),(
'
市场研发部
'),(
'
售后客服部
')
CREATE 
TRIGGER t_Delete 
ON NewPersonnel
FOR 
DELETE
as
BEGIN
    
insert 
into Personnel 
select departmentId,personnelName 
from deleted
END
CREATE 
TRIGGER t_Insert
ON Personnel
FOR 
INSERT
as
BEGIN
    
declare 
@departmentId 
int
    
select 
@departmentId 
= departmentId 
from insertd
    
update department 
set departmentCount
=(
select 
count(
1
from Personnel 
where departmentId
=
@departmentId
where departmentId
=
@departmentId
END
select 
* 
from department
insert 
into NewPersonnel(departmentId,personnelName) 
values (
1,
'
王**
'),(
1,
'
毛*
'),(
1,
'
张**
')
insert 
into NewPersonnel(departmentId,personnelName) 
values (
2,
'
宋**
'),(
2,
'
高**
'),(
2,
'
殷**
')
insert 
into NewPersonnel(departmentId,personnelName) 
values (
3,
'
庄**
'),(
3,
'
施**
'),(
3,
'
胡*
'),(
3,
'
刘**
')
insert 
into NewPersonnel(departmentId,personnelName) 
values (
4,
'
张*
'),(
4,
'
宋**
'),(
4,
'
陈**
')
DELETE 
[
NewPersonnel
] 
where departmentId 
= 
4

 

8、递归触发器

 

任何触发器都可以包含影响同一个表或另一个表的UPDATE/INSERT或DELETE语句。如果启用递归触发器选项,那么改变表中数据的触发器,通过递归执行就可以再次触发自己。在数据库创建时,默认情况下递归触发器选项是禁用的,但可以使用ALTER DATABASE语句来启用它。

 

递归触发器具有复杂特性,可以用它来解决诸如自引用关系这样的复杂关系。使用递归触发器时,需要考虑以下的事项和原则:

1)递归触发器很复杂,必须经过有条理的设计和全面的测试。

2)在任意点的数据修改会触发一系列触发器。尽管提供处理复杂关系的能力,但是如果表要求以特定的顺序更新用户的表时,使用递归触发器就会产生问题

3)所有触发器一起构成一个大事务。任何触发器中的任何位置上的ROLLBACK命令都将取消所有数据输入。所有数据均为擦除,并且无任何数据被放到表中

4)触发器最多只能递归16层。换句话说,如果递归链中的第16个触发器激活了第17个触发器,则结果与发布ROLLBACK命令一样,所有数据将被擦除。

转载于:https://www.cnblogs.com/cxmsky/p/3289116.html

你可能感兴趣的文章
JavaScript动画打开半透明提示层
查看>>
Mybatis生成resulteMap时的注意事项
查看>>
jquery-jqzoom 插件 用例
查看>>
1007. Maximum Subsequence Sum (25)
查看>>
iframe的父子层跨域 用了百度的postMessage()方法
查看>>
图片生成缩略图
查看>>
动态规划 例子与复杂度
查看>>
查看oracle数据库的连接数以及用户
查看>>
【数据结构】栈结构操作示例
查看>>
中建项目环境迁移说明
查看>>
三.野指针和free
查看>>
activemq5.14+zookeeper3.4.9实现高可用
查看>>
TCP/IP详解学习笔记(3)IP协议ARP协议和RARP协议
查看>>
简单【用户输入验证】
查看>>
python tkinter GUI绘制,以及点击更新显示图片
查看>>
CS0103: The name ‘Scripts’ does not exist in the current context解决方法
查看>>
20130330java基础学习笔记-语句_for循环嵌套练习2
查看>>
Spring面试题
查看>>
窥视SP2010--第一章节--SP2010开发者路线图
查看>>
C语言栈的实现
查看>>