48. SQL- 触发器之DML 触发器(1)

触发器

 

触发器分类

在SQLServer 中,触发器可以分为两大类:DML 器和DDL

DML 触发器:

DML触发器是当数据库服务器中发生数据操作语言(Data Manipulation

Language)事件时执行的存储过程。

DML 器又分After 器和Instead Of

○1 、After 触发器:这类触发器是在记录已经改变完之后(after),才会被激活执行,它主要是用于记录变更后的处理或检查,一旦发现错误,也可以用RollbackTransaction 语句来回滚本次的操作。即AFTER 触发器在执行INSERTUPDATEDELETE 语句的操作之后执行

○2 、InsteadOf 触发器:这类触发器一般是用来取代原本的操作,在记录变更之前发生的,它并不去执行原来SQL 语句里的操作(Insert、Update、Delete),

而去执行触发器本身所定义的操作。INSTEADOF 触发器代替INSERT,UPDATE DELETE语句执行

 

触发器工作原理

 

DML 器工作原理:

在SQLServer 里,为每个DML 触发器都定义了两个特殊的表,一个是插入表

Inserted),一个是删除表(Deleted)。这两个表是建在数据库服务器的内存中的,是由系统管理的逻辑表,而不是真正存储在数据库中的物理表。对于这两个表,用户只有读取的权限,没有修改的权限。这两个表的结构与触发器所在数据表的结构是完全一致的,当触发器的工作完成之后,这两个表也将会从内存中删除。

插入表里存放的是更新前的记录:对于插入记录操作来说,插入表里存放的是要插

入的数据;对于更新记录操作来说,插入表里存放的是要更新的记录。

删除表里存放的是更新后的记录:对于更新记录操作来说,删除表里存放的是更新

前的记录(更新完后即被删除);对于删除记录操作来说,删除表里存入的是被删除的旧记录。

○.After 触发器的工作原理

After触发器是在记录变更完之后才被激活执行的。以删除记录为例:当SQL

Server接收到一个要执行删除操作的SQL 语句时,SQL Server 先将要删除的记录存放在删除表里,然后把数据表里的记录删除,再激活After 触发器,执行After触发器里的SQL 语句。执行完毕之后,删除内存中的删除表,退出整个操作。

DEMO:在产品库存表里,如果要删除一条产品记录,在删除记录时,触发器可以检查该产品库存数量是否为零,如果不为零则取消删除操作。看一下数据库是怎么操作的:

(1)接收SQL 语句,将要从产品库存表里删除的产品记录取出来,放在删除表里。

(2)从产品库存表里删除该产品记录。

(3)从删除表里读出该产品的库存数量字段,判断是不是为零,如果为零的话,

完成操作,从内存里清除删除表;如果不为零的话,用RollbackTransaction 语句来回滚操作。

○2 、InsteadOf 触发器的工作原理

InsteadOf 触发器与After 触发器不同。After 触发器是在Insert、Update和Delete

操作完成后才激活的,而Instead Of 触发器,是在这些操作进行之前就激活了,并且不再去执行原来的SQL 操作,而去运行触发器本身的SQL 语句。

 

设计DML 触发器的注意事项及技巧

设计触发器的限制

在触发器中,有一些SQL 语句是不能使用的,这些语句包括:不能使用的语句语句功能

Alter Database 修改数据库

Create Database 新建数据库

Drop Database 删除数据库

Load Database 导入数据库

Load Log 导入日志

Reconfigure 更新配置选项

Restore Database 还原数据库

Restore Log 还原数据库日志

另外,在对作为触发操作的目标的表或视图使用了下面的SQL 语句时,不允许在DML触发器里再使用这些语句:

INSERT, UPDATE,或者DELETE 语句

触发器在另一张表上执行INSERT,UPDATE 或者DELETE

不能使用的语句语句功能

Create Index 建立索引

Alter Index 修改索引

Drop Index 删除索引

DBCC Dbreindex 重新生成索引

Alter Partition Function 通过拆分或合并边界值更改分区

Drop Table 删除数据表

Alter Table 修改数据表结构

如何在触器取得字段修改前和修改后的数据

之前介绍过,SQL Server 在为每个触发器都定义了两个虚拟表,一个是插入表

(inserted),一个是删除表(deleted),现在把这两个表存放的数据列表说明一下:

激活触发器的动作Inserted 表 Deleted表

Insert 存放要插入的记录

Update 存放要更新的记录 存放更新前的旧记录

Delete 存放要删除的旧记录

以上面删除库存产品记录为例,在删除时触发器要判断库存数量是否为零,那么判断就应该这么写:

If(Select 库存数量From Deleted)>0

Begin

Print库存数量大于零时不能删除此记录

RollbackTransaction

End

其它注意事

After 触发器只能用于数据表中,Instead Of 触发器可以用于数据表和视图上,但两种触发器都不可以建立在临时表上。

一个数据表可以有多个触发器,但是一个触发器只能对应一个表。

在同一个数据表中,对每个操作(如Insert、Update、Delete)而言可以建立许多个After 触发器,但Instead Of 触发器针对每个操作只有建立一个。

如果针对某个操作即设置了After触发器又设置了Instead Of 触发器,那么Instead of触发器一定会激活,而After 触发器就不一定会激活了。

Truncate Table 语句虽然类似于Delete 语句可以删除记录,但是它不能激活Delete类型的触发器。因为Truncate Table 语句是不记入日志的。

WRITETEXT 语句不能触发Insert 和Update 型的触发器。

不同的SQL 语句,可以触发同一个触发器,如Insert 和Update语句都可以激活同一个触发器。

创建ALTER触发器

语法:

CREATETRIGGER <Schema_Name, sysname, Schema_Name>.<Trigger_Name, sysname,

Trigger_Name>

ON <Schema_Name, sysname, Schema_Name>.<Table_Name, sysname, Table_Name>

AFTER<Data_Modification_Statements, , INSERT,DELETE,UPDATE>

AS

BEGIN

--SET NOCOUNT ON added to prevent extra result sets from

--interfering with SELECT statements.

SETNOCOUNT ON;

--Insert statements for trigger here

END

GO

转换成中文:

CREATETRIGGER 触发器名

ON 数据表名或视图名

AFTERINSERT或DELETE或UPDATE

AS

BEGIN

--这里是要运行的SQL语句

END

GO

参数说明:

CREATE TRIGGER 触发器名:这一句声明SQL 语句是用来建立一个触发器。其中触发器名在所在的数据库里必须是唯一的。由于触发器是建立中数据表或视图中的,所以有很多人都 以为只要是在不同的数据表中,触发器的名称就可以相同,其实触发器的全名(Server.Database.Owner.TriggerName)是必须 唯一的,这与触发器在哪个数据表或视图无关。

ON 数据表名或视图名:这是指定触发器所在的数据表或视图,但是请注意,只有Instead Of 触发器才能建立在视图上。并且,有设置为With Check Option 的视图也不允许建立InsteadOf 触发器。

AFTER INSERT 或 DELETE或UPDATE:这是指定触发器的类型,是After Insert触发器,还是AfterDelete 触发器,或者是After Update 触发器。其中After 可以用For 来代取,它们的意思都是一样的,代表只有在数据表的操作都已正确完成后才会激活的触发器。INSERT、 DELETE和UPDATE 至少要指定一个,当然也可以指定多个,若指定多个时,必须用逗号来分开。其顺序可以任意摆放。

With Encryption:WithEncryption 是用来加密触发器的,放在“On 数据表名或视图名”的后面,“For”的前面。如果使用了这句话,该触发器将会被加密,任何人都看不到触发器的内容了。

DEMO

○1、创建一个insert 触发器

--查看原表数据:

use demo_db

go

select* from orders

--1、创建一个结构与orders一样的空白测试表ordermail,

select*

into ordermail

from orders

where1=2

--2、创建一个触发器,当插入一条数据时,从inserted(临时表)中插入一条数据到ordersmail表中

createtrigger tr_sendordmail

on orders

forinsert

as

insertinto ordermail

select* from inserted

go

--3、插入一条数据:

insertinto orders

select‘a01‘,‘2011-09-04‘,‘cisco‘,‘CH‘,‘5000‘

--4、查看触发结果:

select* from ordermail

分析:

执行insert 插入语句,向表中插入数据行;

触发insert 触发器,向系统临时表inserted 表中插入新行的备份(副本)

触发器检查inserted 表中插入的新行数据,产生一个触发操作,向表ordermail 中写入一行数据

○2、创建一个DELETE 触发器

--1、创建一个触发器,当删除一条数据时,插入一条数据到ordersmial

createtrigger tr_sendordmaila

on orders

fordelete

as

insertinto ordermail

select* from deleted

go

--2、删除数据:

deleteOrders

wherecust=‘cisco‘

--3、看触发结果:

select* from ordermail

select* from Orders

分析:

执行delete 删除语句,删除表中的数据行;

触发delete 删除触发器,向系统临时表的deleted 表中插入被删除的副本

触发器检查deleted 表中被删除的数据,产生一个触发操作,向表ordermail 中写入一行数据

○3、创建一个UPDATE 触发器

--删除表ordermial中的数据

deleteordermail

wheredocno=‘a01‘

select* from ordermail

对比在使用UPDATE 触发器时,从inserteddeleted 表插入数据对比

在使用UPDATE触发器时,从inserted插入数据

--1、创建触发器,当表orders执行一个update操作时,触发操作从inserted表中插入数据到ordermail

createtrigger tr_sendordmaild

on orders

forupdate

as

insertinto ordermail

select* from inserted

go

--2、更新一条数据

updateOrders set cust =‘linkcom‘

go

--3、查看触发结果

select* from ordermail

select* from Orders

返回结果:

从上可以看到,表ordermail 中插入的数据是upadate 后的数据

在使用UPDATE ,从deleted 插入数据

--1、创建触发器,当表orders执行一个update操作时,触发操作从deleted表中插入数据到ordermail中

createtrigger tr_sendordmaile

on orders

forupdate

as

insertinto ordermail

select* from deleted

go

--2、更新一条数据

updateOrders set cust =‘cisco‘

go

--3、查看触发结果

select* from ordermail

select* from Orders

返回:

从上可以看出,表ordermail 中插入的数据是update 前及update后的数据

○4、创建一个列级UPDATE 触发器,当列新某一列时,触发某一动作

--删除之前创建的触发器

droptrigger tr_sendordmail

go

droptrigger tr_sendordmaila

go

droptrigger tr_sendordmaild

go

droptrigger tr_sendordmaile

go

--清空表ordermial 中的数据

deleteordermail

wherecust in (‘cisco‘,‘linkcom‘)

--1、创建一个触发器,当列新表orders 的cust 列时,触发一个操作,从deleted 表中插入数据到ordermail

表中

createtrigger tr_sendordmail

on orders

forupdate

as

ifupdate (cust)

begin

insertinto ordermail

select* from inserted

end

go

--2、同时更新2 条数据,对列docno 及列cust 进行更新

updateOrders

set docno = ‘a01‘

wheredocno = ‘p02‘

updateOrders

set cust =‘MOF‘

wheredocno = ‘a01‘

go

--3、查看触发结果:

select* from ordermail

select* from Orders

可以看出,以上同时对docno及cust 进行更新,但只有更新列cust 时,才触发触发器执行一条插入操作.

○5、当更新某一列某个字段某个值时,触发一个条件,插入ordersmail 一条数据

--1、创建触发器,当列新表orders中列cust中字段值为aaa时,触发触发器,执行一条插入操作

altertrigger tr_sendordmail

on orders

forupdate

as

ifupdate (cust)

begin

if exists (select top 1 1 from insertedwhere cust =‘aaa‘)

begin

insertinto ordermail

select* from inserted

end

end

go

--2、同时更新2 条数据,对列cust 进行更新

updateOrders

set cust =‘mod‘

wheredocno = ‘p03‘

go

updateOrders

set cust =‘aaa‘

wheredocno = ‘p03‘

go

--3、查看触发结果:

select* from ordermail

select* from Orders

可以看出,以上同时对cust进行2 条数据更新,但只有更新列cust 值为aaa 时,才触发触发器执行一条插入操作.

时间: 2024-10-19 01:48:49

48. SQL- 触发器之DML 触发器(1)的相关文章

46. SQL -触发器之概述

触发器   触发器概念: 触发器是一种特殊类型的存储过程,不由用户直接调用.创建触发器时会对其进行定义,以便在对特定表或列作特定类型的数据修改时执行. 触发器总结: 触发器是与数据库和数据表相结合的特殊的存储过程,当数据表有Insert.Update.Delete操作或数据库有Create.Alter.Drop 操作的时候,可以激活触发器,并运行其中的T-SQL 语句. 在SQLServer 2008 中触发器分有DML 触发器和DDL 触发器两种. 其中DML触发器又分为After 触发器和I

49. SQL- 触发器之DML 触发器(2)

其它AFTER触发器操作 设置After 触发器的激活顺序 对于同一个操作,如Insert.Update 或Delete来说,可以建立多个After Insert 触发器,如以下DEMO,已经建立了一个名为―orders_Insert|的触发器,输出一句友好提示"又添加了一种产品":之后再建立一个After Insert 触发器,作用也是输出一句友好提示,提示内容为:―再一次告诉你,你又添加了一种产品|. --1.创建2个触发器 CREATETRIGGER orders_Insert

SQL Server 数据库DML触发器 【一】

今天学习SQL Server数据库中DML触发器(DDL触发器以后有时间继续学习). 当删除一条创建有触发器的表中的内容时,触发器执行SQL语句. 1.首相先创建一张表,表名称是 [Test] , 内有三个字段,分别是 [Name], Sex, Place. 1 use inter 2 create table Test 3 ( 4 [Name] varchar(20) not null, 5 Sex varchar(20) not null, 6 Place varchar(20) not n

SQL Server如何用触发器捕获DML操作的会话信息

原文:SQL Server如何用触发器捕获DML操作的会话信息 需求背景 上周遇到了这样一个需求,维护人员发现一个表的数据经常被修改,由于历史原因:文档缺少:以及维护人员的经常变更,导致他们对系统也业务也不完全熟悉,他们也不完全清楚哪些系统和应用程序会对这个表的数据进行操作.现在他们想找出有哪些服务器,哪些应用程序会对这个表进行INSERT.UPDATE操作.那么问题来了,怎么去解决这个问题呢? 解决方案 由于数据库版本是标准版,我们选择了使用触发器来捕获进行DML操作的会话的相关信息,例如,H

SQL语句(二十一)—— 触发器(DML触发器)

触发器 一 .触发器概述(特殊的存储过程) 定义: 在修改指定表值的数据时执行的 存储过程. 不同的是 : 执行存储过程要使用EXEC语句来调用,而触发器的执行不需要使用EXEC语句来调用. 作用: 实现由主键和外键所不能保证的复制的参照完整性和数据的一致性 他能够对数据库中的相关表进行级联修改 提供比 CHECK约束 更复杂的数据完整性,并自定义错误信息. 分类: 数据操作语言触发器 DML 数据库操作语言 : update,Delete 数据定义语言触发器 DDL 记录数据库更改事件 二.创

杂谈--DML触发器学习

触发器按类型分为三类: 1. DML 触发器,在数据变更时触发: 2. DDL 触发器,在修改数据库级别或实例级别对象时触发: 3. Login 触发器,在用户登录时触发: 最常见的是DML触发器,DML触发器又可以分为两类: INSTEAD OF触发器和AFTER触发器(部分书上有提到FOR触发器,其实就是AFTER 触发器,只是写法不同而已). 从功能来看,INSTEAD OF触发器用来替换实际的数据修改操作,而AFTER触发器用来在实际操作完成后进行后续操作.例如对于DELETE操作,如果

【PLSQL】详解SQL中的trigger(触发器)

本篇主要内容如下: 8.1 触发器类型 8.1.1 DML触发器 8.1.2 替代触发器 8.1.3 系统触发器 8.2 创建触发器 8.2.1 触发器触发次序 8.2.2 创建DML触发器 8.2.3 创建替代(INSTEAD OF)触发器 8.2.3 创建系统事件触发器 8.2.4 系统触发器事件属性 8.2.5 使用触发器谓词 8.2.6 重新编译触发器 8.3 删除和使能触发器 8.4 触发器和数据字典 8.5   数据库触发器的应用举例 触发器是许多关系数据库系统都提供的一项技术.在O

47. SQL- 触发器之DDL 触发器

触发器工作原理     DDL触发器 与DML 触发器不同,DDL 触发器不会为响应针对表或视图的UPDATE.INSERT或DELETE 语句而激发. 响应多种数据定义语言(DDL) 语句而激发.主要是以CREATE.ALTER和DROP 开头的语句. DDL 触发器可用于管理任务,例如审核和控制数据库操作. DDL 触发器的作用域: l 数据库作用域 l 服务器作用域 在响应当前数据库或服务器中处理的Transact-SQL 事件时,将激发DDL 触发器.触发器的作用域取决于事件(数据库作用

Oracle之PL/SQL学习笔记之触发器

Oracle之PL/SQL学习笔记之触发器 触发器是许多关系数据库系统都提供的一项技术.在ORACLE系统里,触发器类似过程和函数,都有声明,执行和异常处理过程的PL/SQL块. 触发器在数据库里以独立的对象存储,它与存储过程和函数不同的是,存储过程与函数需要用户显示调用才执行,而触发器是由一个事件来启动运行. 即触发器是当某个事件发生时自动地隐式运行.并且,触发器不能接收参数.所以运行触发器就叫触发或点火(firing).ORACLE事件指的是对数据库的表进行的INSERT. UPDATE及D