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

其它AFTER触发器操作

设置After 触发器的激活顺序

对于同一个操作,如Insert、Update 或Delete来说,可以建立多个After Insert 触发器,如以下DEMO,已经建立了一个名为―orders_Insert‖的触发器,输出一句友好提示“又添加了一种产品”;之后再建立一个After Insert 触发器,作用也是输出一句友好提示,提示内容为:―再一次告诉你,你又添加了一种产品‖。

--1、创建2个触发器

CREATETRIGGER orders_Insert

ON orders

AFTERINSERT

AS

BEGIN

print‘又添加了一种产品‘

END

GO

CREATETRIGGER orders_Insert1

ON orders

AFTERINSERT

AS

BEGIN

print‘再一次告诉你,你又添加了一种产品‘

END

GO

--2、插入一条数据

insertinto Orders

values(‘a02‘,‘2011-09-04‘,‘cisco‘,‘USA‘,‘7000‘)

--返回:

从上可以看出,一条insert into 语句,触发了2 个触发器

当同一个操作定义的触发器越来越多的时候,触发器被激活的次序就会变得越来越重要了。在SQLServer 2008 里,用存储过程【sp_settriggerorder】可以为每一个操作各指定一个最先执行的After 触发器和最后执行的After 触发器。sp_settriggerorder 语法如下:

sp_settriggerorder[ @triggername = ] ‘[triggerschema. ] triggername‘

, [ @order = ] ‘value‘

, [ @stmttype = ] ‘statement_type‘

[, [ @namespace = ] { ‘DATABASE‘| ‘SERVER‘ |NULL } ]

翻译成中文就是:

sp_settriggerorder触发器名,

激活次序,

激活触发器的动作

参数:

触发器名,要用单引号括起来,因为它是一个字符串。

激活次序可以为First、Last和None:First 是指第一个要激活的触发器;Last 是指它最后一个要激活的触发器;None 是不指激活序,由程序任意触发。

激活触发器的动作可以是:Insert、Update 和Delete。

上面的例子里,先激活的是【orders_Insert】触发器,后激活的是【orders_Insert1】

触发器。如果把【orders_Insert1】触发器设为First 触发器,把【orders_Insert】触发器设为Last 触发器,那么结果将会完全不一样。设置语句如下:

Exec sp_settriggerorder

‘orders_Insert1‘,‘First‘,‘Insert‘

go

Exec sp_settriggerorder

‘orders_Insert‘,‘Last‘,‘Insert‘

Go

--插入一条新的数据

insertinto Orders

values(‘a03‘,‘2011-09-04‘,‘MII‘,‘USA‘,‘7000‘)

触发器返回结果:

在设置After 触发器激活顺序时,还有几点是需要注意的:

每个操作最多只能设一个First触发器和一个Last 触发器。

如果要取消已经设好的First 触发器或Last 触发器,只要把它们设为None 触发器即可。

如果用Alter 命令修改过触发器内容后,该触发器会自动变成None 触发器。所以用Alter 命令也可以用来取消已经设好的First 触发器或Last 触发器。

只有After 触发器可以设置激活次序,Instead Of 触发器不可以设置激活次序。

激活触发器的动作必须和触发器内部的激活动作一致。举例说明:After Insert 触发器,只能为Insert操作设置激活次序,不能为Delete 操作设置激活次序。以下的设置是错误的:

Execsp_settriggerorder

‘orders_Insert1‘,‘First‘,Update

go

触发器的嵌套

当一个触发器执行时,能够触活另一个触发器,这种情况就是触发器的嵌套。在SQL Server 2008 里,触发器能够嵌套到32 层。

如果不想对触发器进行嵌套的话,可以通过【允许触发器激活其他触发器】的服务器配置选项来控制。但不管此设置是什么,都可以嵌套Instead Of 触发器。设置触发器嵌套的选项更改方法为:

(1)打开ManagementStudio,在【对象资源管理】中,右击服务器名,并选择【属性】选项。

(2)单击【高级】节点。

(3)在【杂项】里设置【允许触发器激活其他触发器】为True 或False。

--1、创建一个测试表,用于记录操作记录

在DEMO_DB数据库里建一个操作记录表,用来记录所有数据表的操作,无论是对哪个数据表进行了插入、更新或删除,都可以把操作内容和操作时间记录到操作记录表里。下面是建立操作记录表的SQL 语句:

CREATETABLE Operation

(

seq_numint IDENTITY(1,1) NOT NULL, --编号

op_tablevarchar(50) NOT NULL, --操作表名

op_Sentencevarchar(2000) NOT NULL, --操作语句

op_Contentvarchar(2000) NOT NULL, --操作类容

op_timedatetime NOT NULL --操作时间

CONSTRAINTDF_Operation_time DEFAULT (getdate()), --创建一个默认约束

CONSTRAINTPK_Operation PRIMARY KEYCLUSTERED --针对seq_num列做一个主键约束

( seq_num ASC )

WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]

)

ON [PRIMARY]

GO

{ 使用 IGNORE_DUP_KEY选项来处理重复值。

在创建或修改唯一索引或约束时,您可以将IGNORE_DUP_KEY选项设置为ON 或 OFF。当索引创建后,此选项指定对操作多行的INSERT 语句中所出现的重复键值错误的响应方式。

当 IGNORE_DUP_KEY 设置为OFF(默认设置)时,如果有一行或多行含有重复键值,则SQLServer 数据库引擎 将拒绝语句操作的所有行。当设置为ON 时,只有包含重复键值的行被拒绝后,才能添加非重复键值。

例如,如果一个单条语句向某个具有唯一索引的表中插入20 行,而其中 10 行含有重复键值,则默认情况下全部20 行都将被拒绝。但是,如果索引选项IGNORE_DUP_KEY 设置为ON,则只有10 个重复键值会被拒绝,其他10 个非重复键值将插入到表中。}

--2、创建一个After Insert 触发器,触发器的作用是输入一条语句:“数据库又有记录变动

了”。语句如下:

CREATETRIGGER Operation_Insert

ON Operation

AFTERINSERT

AS

BEGIN

print‘数据库又有记录变动了‘

END

GO

--3、创建一个测试表type,用于插入数据时,触发操作

createtable type

(type_name nvarchar(15),type_descrnvarchar(max))

--4、创建立一个After Insert 触发器

当在type 表里插入一条记录的时候,该触发器向操作记录表里插入一条记录,而在操作记录表里插入记录时,将会触发操作记录表里的【Operation_Insert】触发器。

CREATETRIGGER type_Insert

ONtype

AFTERINSERT

AS

BEGIN

Declare

@type_namenvarchar(15), --定义变量@type_name

@type_descrnvarchar(max) --定义变量@type_descr

set @type_name= (Selecttype_name from inserted)

--为@type_name附值为inserted表中type_name

set @type_descr= (Select type_descr from inserted)

--为@type_descr附值为inserted表中type_descr

INSERTINTO Operation(op_table,op_Sentence,op_Content)

–-触发触发器时,将操作内容插入到操作记录表

VALUES(‘type‘,‘insert‘,‘type_name:‘+@type_name+‘,type_descr:‘+@type_descr)

END

GO

--4、在type 表中插入一条记录

insertinto type

values(‘book‘,‘cisco_bsci‘)

返回:

数据库又有记录变动了

(1 行受影响)

(1 行受影响)

在【消息】对话框可以看到―数据库又有记录变动了‖,这说明,触发器[Operation_Insert]

已经被嵌套激活了

--5、查看表operation 内容

select* from type

select* from Operation

返回结果:

--6、如果把【允许触发器激活其他触发器】的选项设为False,再看看运行结果:

insertinto type

values(‘book‘,‘cisco_ts‘)

返回:

(1 行受影响)

(1 行受影响)

可以看到并未触发嵌套触发器[Operation_Insert]

select* from type

select* from Operation

返回 :

触发器的递归

触发器的递归是指,一个触发器从其内部又一次激活该触发器。例如一个Insert 触发器的内部还有一条对本数据表插入记录的SQL 语句,那么这个插入语句就有可能再一次激活这个触发器本身。当然,这种递归的触发器内部还会有判断语句,要一定的情况下才会执行那个SQL 语句,否则的话,就会变成死循环了。

上面的例子说的是直接递归的触发器,还有一种是间接递归的触发器,举例说明:当向A 表插入一条记录时,激活了A 表的Insert 触发器,A表的Insert 触发器里有一个SQL语句是对B 表进行Insert 操作的,而在 B 表的Insert触发器里也有一句话是对A 表进行Insert 操作的。这样就是触发器的间接递归。

一般情况来说,SQL Server 服务器是不允许递归的,如果要打开触发器递归的功能,同样是将【允许触发器激活其他触发器】设为True。

设计Instead Of 触发器

InsteadOf 触发器与After 触发器的工作流程是不一样的。After 触发器是在SQL

Server服务器接到执行SQL 语句请求之后,先建立临时的Inserted 表和Deleted表,然后实际更改数据,最后才激活触发器的。而InsteadOf 触发器看起来就简单多了,在SQLServer 服务器接到执行SQL 语句请求后,先建立临时的Inserted 表和Deleted表,然后就触发了Instead Of 触发器,至于那个SQL 语句是插入数据、更新数据还是删除数据,就一概不管了,把执行权全权交给了Instead Of 触发器,由它去完成之后的操作

 

Instead Of 触发器的使用范围

InsteadOf 触发器可以同时在数据表和视图中使用,通常在以下几种情况下,建议使用Instead Of 触发器:

数据库里的数据禁止修改:例如电信部门的通话记录是不能修改的,一旦修改,则通话费用的计数将不正确。在这个时候,就可以用Instead Of 触发器来跳过Update 修改记录的SQL 语句。

有可能要回滚修改的SQL语句:例在订单明细表里,折扣字段不能大于0.6,如果插入记录时,折扣大于0.6 的话,回滚操作。如果用Instead Of 触发器,在判断折扣大于0.6 时,就中止了更新操作,避免在修改数据之后再回滚操作,减少服务器负担。

在视图中使用触发器:因为After 触发器不能在视图中使用,如果想在视图中使用触发器,就只能用InsteadOf 触发器。

用自己的方式去修改数据:如不满意SQL直接的修改数据的方式,可用Instead Of触发器来控制数据的修改方式和流程。

创建Instead of 触发器

(1)、语法:

CREATETRIGGER 触发器名

ON 数据表名或视图名

InsteadOf INSERT或DELETE或UPDATE

AS

BEGIN

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

END

GO

从上面可以看得出,InsteadOf 触发器与After 触发器的语法几乎一致,只是简单地把After 改为Instead Of。

DEMO:使用InsteadOf 触发器,在判断表orders 价格大于10000时,就中止了更新操作,避免在修改数据之后再回滚操作,减少服务器负担。现将原来的触发器改为InsteadOf 触发器:

--1、使用AFTER 创建触发器:

CREATETRIGGER orders_Insert

ON orders

AFTERINSERT

AS

BEGIN

if (Select ratefrom inserted)>8000

begin

print‘rate Not more than 8000‘

RollbackTransaction

end

END

GO

--插入一条语句,其中rate>10000,查看返回结果

insertinto Orders

values(‘a06‘,‘2011-09-17‘,‘cisco‘,‘usa‘,‘8500‘)

--返回:

rateNot more than 8000

消息3609,级别16,状态1,第1 行

事务在触发器中结束。批处理已中止。

--2、使用Instead Of 创建触发器:

CREATETRIGGER orders_Insert

ON orders

InsteadOf INSERT

AS

BEGIN

SETNOCOUNT ON;

declare

@docnochar(20),

@docdatedatetime,

@custnvarchar(200),

@carrencychar(3),

@ratenumeric(5)

set @docno = (selectdocno from inserted)

set @docdate = (selectdocdate from inserted)

set @cust = (selectcust from inserted)

set @carrency = (selectcarrency from inserted)

set @rate = (selectrate from inserted)

if (@rate)>1000

print‘rate Not more than 1000‘

end

--插入一条语句,其中rate>1000,查看返回结果

insertinto Orders

values(‘a07‘,‘2011-09-18‘,‘cisco‘,‘usa‘,‘5000‘)

--返回:

rateNot more than 1000

(1 行受影响)

管理DML 触发器

  1. 查看DML触发器

使用Management Studio

打开ManagementStudio →数据库 → 表 → 触发器 →

双击要查看的触发器名,Management Studio 自动弹出一个

【查询编辑器】对话框,对话框里显示的是该触发器的内容

 

使用系储过看触

SP_HELP

SP_HELPTEXT

DEMO:

sp_helporders_insert1

go

sp_helptextorders_insert1

go

返回:

修改触发器

语法:

ALTERTRIGGER 触发器名

ON 数据表名或视图名

AFTERINSERT或DELETE或UPDATE

AS

BEGIN

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

END

GO

重命名触发器:

sp_rename‘旧触发器名‘,‘新触发器名‘

D、删除触发器:

删除:

droptrigger ‘触发器名‘

禁用:

Altertable 数据表名

Disable或Enable trigger 触发器名或ALL

用Disable可以禁用触发器,用Enable 可以启用触发器;如果要禁用或启用所有触发器,用―ALL‖来代替触发器名

时间: 2024-10-12 09:24:02

49. SQL- 触发器之DML 触发器(2)的相关文章

46. SQL -触发器之概述

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

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

触发器   触发器分类 在SQLServer 中,触发器可以分为两大类:DML 触发器和DDL 触发器 DML 触发器: DML触发器是当数据库服务器中发生数据操作语言(Data Manipulation Language)事件时执行的存储过程. DML 触发器又分为两类:After 触发器和Instead Of 触发器 ○1 .After 触发器:这类触发器是在记录已经改变完之后(after),才会被激活执行,它主要是用于记录变更后的处理或检查,一旦发现错误,也可以用RollbackTrans

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