当前位置: 数据库>sqlserver
SQL触发器实例讲解
来源: 互联网 发布时间:2014-10-04
本文导语: SQL触发器实例1 定义: 何为触发器?在SQL Server里面也就是对某一个表的一定的操作,触发某种条件,从而执行的一段程序。触发器是一个特殊的存储过程。 常见的触发器有三种:分别应用于Insert , Update , Delete 事件。 我为什么...
SQL触发器实例1
定义: 何为触发器?在SQL Server里面也就是对某一个表的一定的操作,触发某种条件,从而执行的一段程序。触发器是一个特殊的存储过程。
常见的触发器有三种:分别应用于Insert , Update , Delete 事件。
我为什么要使用触发器?比如,这么两个表:
Create Table Student( --学生表
StudentID int primary key, --学号
....
)
Create Table BorrowRecord( --学生借书记录表
BorrowRecord int identity(1,1), --流水号
StudentID int , --学号
BorrowDate datetime, --借出时间
ReturnDAte Datetime, --归还时间
...
)
用到的功能有:
1.如果我更改了学生的学号,我希望他的借书记录仍然与这个学生相关(也就是同时更改借书记录表的学号);
2.如果该学生已经毕业,我希望删除他的学号的同时,也删除它的借书记录。
等等。
这时候可以用到触发器。对于1,创建一个Update触发器:
Create Trigger truStudent
On Student --在Student表中创建触发器
for Update --为什么事件触发
As --事件触发后所要做的事情
if Update(StudentID)
begin
Update BorrowRecord
Set StudentID=i.StudentID
From BorrowRecord br , Deleted d ,Inserted i --Deleted和Inserted临时表
Where br.StudentID=d.StudentID
end
理解触发器里面的两个临时的表:Deleted , Inserted 。注意Deleted 与Inserted分别表示触发事件的表“旧的一条记录”和“新的一条记录”。
一个数据库系统中有两个虚拟表用于存储在表中记录改动的信息,分别是:
虚拟表Inserted 虚拟表Deleted
在表记录新增时 存放新增的记录 不存储记录
修改时 存放用来更新的新记录 存放更新前的记录
删除时 不存储记录 存放被删除的记录
一个Update 的过程可以看作为:生成新的记录到Inserted表,复制旧的记录到Deleted表,然后删除Student记录并写入新纪录。
对于2,创建一个Delete触发器
Create trigger trdStudent
On Student
for Delete
As
Delete BorrowRecord
From BorrowRecord br , Delted d
Where br.StudentID=d.StudentID
从这两个例子我们可以看到了触发器的关键:A.2个临时的表;B.触发机制。
SQL触发器实例2
/*
建立虚拟测试环境,包含:表[卷烟库存表],表[卷烟销售表]。
请大家注意跟踪这两个表的数据,体会触发器到底执行了什么业务逻辑,对数据有什么影响。
为了能更清晰的表述触发器的作用,表结构存在数据冗余,且不符合第三范式,这里特此说明。
*/
USE Master
GO
IF EXISTS (SELECT NAME FROM SYSOBJECTS WHERE XTYPE = 'U' AND NAME = '卷烟库存表')
DROP TABLE 卷烟库存表
GO
IF EXISTS (SELECT NAME FROM SYSOBJECTS WHERE XTYPE = 'U' AND NAME = '卷烟销售表')
DROP TABLE 卷烟销售表
GO
--业务规则:销售金额 = 销售数量 * 销售单价 业务规则。
CREATE TABLE 卷烟销售表
(
卷烟品牌 VARCHAR(40) PRIMARY KEY NOT NULL,
购货商 VARCHAR(40) NULL,
销售数量 INT NULL,
销售单价 MONEY NULL,
销售金额 MONEY NULL
)
GO
--业务规则:库存金额 = 库存数量 * 库存单价 业务规则。
CREATE TABLE 卷烟库存表
(
卷烟品牌 VARCHAR(40) PRIMARY KEY NOT NULL,
库存数量 INT NULL,
库存单价 MONEY NULL,
库存金额 MONEY NULL
)
GO
--创建触发器,示例1
/*
创建触发器[T_INSERT_卷烟库存表],这个触发器较简单。
说明: 每当[卷烟库存表]发生 INSERT 动作,则引发该触发器。
触发器功能: 强制执行业务规则,保证插入的数据中,库存金额 = 库存数量 * 库存单价。
注意: [INSERTED]、[DELETED]为系统表,不可创建、修改、删除,但可以调用。
重要: 这两个系统表的结构同插入数据的表的结构。
*/
IF EXISTS (SELECT NAME FROM SYSOBJECTS WHERE XTYPE = 'TR' AND NAME = 'T_INSERT_卷烟库存表')
DROP TRIGGER T_INSERT_卷烟库存表
GO
CREATE TRIGGER T_INSERT_卷烟库存表
ON 卷烟库存表
FOR INSERT
AS
--提交事务处理
BEGIN TRANSACTION
--强制执行下列语句,保证业务规则
UPDATE 卷烟库存表
SET 库存金额 = 库存数量 * 库存单价
WHERE 卷烟品牌 IN (SELECT 卷烟品牌 from INSERTED)
COMMIT TRANSACTION
GO
/*
针对[卷烟库存表],插入测试数据:
注意,第一条数据(红塔山新势力)中的数据符合业务规则,
第二条数据(红塔山人为峰)中,[库存金额]空,不符合业务规则,
第三条数据(云南映像)中,[库存金额]不等于[库存数量]乘以[库存单价],不符合业务规则。
第四条数据库存数量为0。
请注意在插入数据后,检查[卷烟库存表]中的数据是否 库存金额 = 库存数量 * 库存单价。
*/
INSERT INTO 卷烟库存表(卷烟品牌,库存数量,库存单价,库存金额)
SELECT '红塔山新势力',100,12,1200 UNION ALL
SELECT '红塔山人为峰',100,22,NULL UNION ALL
SELECT '云南映像',100,60,500 UNION ALL
SELECT '玉溪',0,30,0
GO
--查询数据
SELECT * FROM 卷烟库存表
GO
/*
结果集
RecordId 卷烟品牌 库存数量 库存单价 库存金额
-------- ------------ -------- ------- ---------
1 红塔山新势力 100 12.0000 1200.0000
2 红塔山人为峰 100 22.0000 2200.0000
3 云南映像 100 60.0000 6000.0000
4 玉溪 0 30.0000 .0000
(所影响的行数为 4 行)
*/
--触发器示例2
/*
创建触发器[T_INSERT_卷烟销售表],该触发器较复杂。
说明: 每当[卷烟库存表]发生 INSERT 动作,则引发该触发器。
触发器功能: 实现业务规则。
业务规则: 如果销售的卷烟品牌不存在库存或者库存为零,则返回错误。
否则则自动减少[卷烟库存表]中对应品牌卷烟的库存数量和库存金额。
*/
IF EXISTS (SELECT NAME FROM SYSOBJECTS WHERE XTYPE = 'TR' AND NAME = 'T_INSERT_卷烟销售表')
DROP TRIGGER T_INSERT_卷烟销售表
GO
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
库存数量
sql server 触发器实例:特定字段更新时触发Update触发器
SQL Server 触发器 表的特定字段更新时,触发Update触发器
sql server 禁用与启用触发器的语句
SQL2000能不能够象Access2000那样自动编号?(用触发器行不行?如何做?)
MySQL与SQL的触发器的不同写法
查看数据库中所有触发器的sql语句
SQL Server误区30日谈 第4天 DDL触发器就是INSTEAD OF触发器
sql server 触发器实例(判断是插入、删除,还是修改)
sql update 触发器 可获得被update的行的信息
sql server触发器的简单例子
Oracle创建主键自增表(sql语句实现)及触发器应用
使用sql脚本创建触发器的例子
sql server跨服务器触发器的例子
ORACLE PL/SQL 触发器编程篇介绍
sql server添加、更新、删除触发器的例子
sql 触发器使用例子
sql不常用函数总结以及事务,增加,删除触发器
sql server 触发器实例分享(1)
简单触发器的使用 献给SQL初学者
定义: 何为触发器?在SQL Server里面也就是对某一个表的一定的操作,触发某种条件,从而执行的一段程序。触发器是一个特殊的存储过程。
常见的触发器有三种:分别应用于Insert , Update , Delete 事件。
我为什么要使用触发器?比如,这么两个表:
代码如下:
Create Table Student( --学生表
StudentID int primary key, --学号
....
)
Create Table BorrowRecord( --学生借书记录表
BorrowRecord int identity(1,1), --流水号
StudentID int , --学号
BorrowDate datetime, --借出时间
ReturnDAte Datetime, --归还时间
...
)
用到的功能有:
1.如果我更改了学生的学号,我希望他的借书记录仍然与这个学生相关(也就是同时更改借书记录表的学号);
2.如果该学生已经毕业,我希望删除他的学号的同时,也删除它的借书记录。
等等。
这时候可以用到触发器。对于1,创建一个Update触发器:
代码如下:
Create Trigger truStudent
On Student --在Student表中创建触发器
for Update --为什么事件触发
As --事件触发后所要做的事情
if Update(StudentID)
begin
Update BorrowRecord
Set StudentID=i.StudentID
From BorrowRecord br , Deleted d ,Inserted i --Deleted和Inserted临时表
Where br.StudentID=d.StudentID
end
理解触发器里面的两个临时的表:Deleted , Inserted 。注意Deleted 与Inserted分别表示触发事件的表“旧的一条记录”和“新的一条记录”。
一个数据库系统中有两个虚拟表用于存储在表中记录改动的信息,分别是:
虚拟表Inserted 虚拟表Deleted
在表记录新增时 存放新增的记录 不存储记录
修改时 存放用来更新的新记录 存放更新前的记录
删除时 不存储记录 存放被删除的记录
一个Update 的过程可以看作为:生成新的记录到Inserted表,复制旧的记录到Deleted表,然后删除Student记录并写入新纪录。
对于2,创建一个Delete触发器
代码如下:
Create trigger trdStudent
On Student
for Delete
As
Delete BorrowRecord
From BorrowRecord br , Delted d
Where br.StudentID=d.StudentID
从这两个例子我们可以看到了触发器的关键:A.2个临时的表;B.触发机制。
SQL触发器实例2
代码如下:
/*
建立虚拟测试环境,包含:表[卷烟库存表],表[卷烟销售表]。
请大家注意跟踪这两个表的数据,体会触发器到底执行了什么业务逻辑,对数据有什么影响。
为了能更清晰的表述触发器的作用,表结构存在数据冗余,且不符合第三范式,这里特此说明。
*/
USE Master
GO
IF EXISTS (SELECT NAME FROM SYSOBJECTS WHERE XTYPE = 'U' AND NAME = '卷烟库存表')
DROP TABLE 卷烟库存表
GO
IF EXISTS (SELECT NAME FROM SYSOBJECTS WHERE XTYPE = 'U' AND NAME = '卷烟销售表')
DROP TABLE 卷烟销售表
GO
--业务规则:销售金额 = 销售数量 * 销售单价 业务规则。
CREATE TABLE 卷烟销售表
(
卷烟品牌 VARCHAR(40) PRIMARY KEY NOT NULL,
购货商 VARCHAR(40) NULL,
销售数量 INT NULL,
销售单价 MONEY NULL,
销售金额 MONEY NULL
)
GO
--业务规则:库存金额 = 库存数量 * 库存单价 业务规则。
CREATE TABLE 卷烟库存表
(
卷烟品牌 VARCHAR(40) PRIMARY KEY NOT NULL,
库存数量 INT NULL,
库存单价 MONEY NULL,
库存金额 MONEY NULL
)
GO
--创建触发器,示例1
/*
创建触发器[T_INSERT_卷烟库存表],这个触发器较简单。
说明: 每当[卷烟库存表]发生 INSERT 动作,则引发该触发器。
触发器功能: 强制执行业务规则,保证插入的数据中,库存金额 = 库存数量 * 库存单价。
注意: [INSERTED]、[DELETED]为系统表,不可创建、修改、删除,但可以调用。
重要: 这两个系统表的结构同插入数据的表的结构。
*/
IF EXISTS (SELECT NAME FROM SYSOBJECTS WHERE XTYPE = 'TR' AND NAME = 'T_INSERT_卷烟库存表')
DROP TRIGGER T_INSERT_卷烟库存表
GO
CREATE TRIGGER T_INSERT_卷烟库存表
ON 卷烟库存表
FOR INSERT
AS
--提交事务处理
BEGIN TRANSACTION
--强制执行下列语句,保证业务规则
UPDATE 卷烟库存表
SET 库存金额 = 库存数量 * 库存单价
WHERE 卷烟品牌 IN (SELECT 卷烟品牌 from INSERTED)
COMMIT TRANSACTION
GO
/*
针对[卷烟库存表],插入测试数据:
注意,第一条数据(红塔山新势力)中的数据符合业务规则,
第二条数据(红塔山人为峰)中,[库存金额]空,不符合业务规则,
第三条数据(云南映像)中,[库存金额]不等于[库存数量]乘以[库存单价],不符合业务规则。
第四条数据库存数量为0。
请注意在插入数据后,检查[卷烟库存表]中的数据是否 库存金额 = 库存数量 * 库存单价。
*/
INSERT INTO 卷烟库存表(卷烟品牌,库存数量,库存单价,库存金额)
SELECT '红塔山新势力',100,12,1200 UNION ALL
SELECT '红塔山人为峰',100,22,NULL UNION ALL
SELECT '云南映像',100,60,500 UNION ALL
SELECT '玉溪',0,30,0
GO
--查询数据
SELECT * FROM 卷烟库存表
GO
/*
结果集
RecordId 卷烟品牌 库存数量 库存单价 库存金额
-------- ------------ -------- ------- ---------
1 红塔山新势力 100 12.0000 1200.0000
2 红塔山人为峰 100 22.0000 2200.0000
3 云南映像 100 60.0000 6000.0000
4 玉溪 0 30.0000 .0000
(所影响的行数为 4 行)
*/
--触发器示例2
/*
创建触发器[T_INSERT_卷烟销售表],该触发器较复杂。
说明: 每当[卷烟库存表]发生 INSERT 动作,则引发该触发器。
触发器功能: 实现业务规则。
业务规则: 如果销售的卷烟品牌不存在库存或者库存为零,则返回错误。
否则则自动减少[卷烟库存表]中对应品牌卷烟的库存数量和库存金额。
*/
IF EXISTS (SELECT NAME FROM SYSOBJECTS WHERE XTYPE = 'TR' AND NAME = 'T_INSERT_卷烟销售表')
DROP TRIGGER T_INSERT_卷烟销售表
GO
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
库存数量