网络编程
位置:首页>> 网络编程>> 数据库>> SQL SERVER数据库开发之触发器的应用

SQL SERVER数据库开发之触发器的应用

作者:栽培者 来源:51js 发布时间:2008-06-23 13:09:00 

标签:触发器,sql,server,数据库

不知道在坛子里有多少朋友使用触发器,如果你已经对触发器很了解了,那么请跳过此文,如果你还没有使用过触发器的话,那就让我们来认识一下吧。

相关阅读:SQL SERVER数据库开发之asp存储过程应用

触发器定义:

触发器是一种特殊类型的存储过程,不由用户直接调用。当使用下面的一种或多种数据修改操作在指定表中对数据进行修改时,触发器会生效:Update、Insert 或 Delete。触发器可以查询其它表,而且可以包含复杂的 SQL 语句。它们主要用于强制复杂的业务规则或要求。

触发器一个应用就是保持和维护数据的完整性及合法性,那么怎么来理解呢?就是说你可以在程序里提交任意数据,然后由触发器来判断数据的完整性及合法性,当然这里只是举例说明,实际应用中不推荐这样用,应该由应用程序来验证数据的完整性及合法性。

  下面我还是以实例的方式来描述触发器的应用。

  设:当前数据库中有“uMateriel”和“uRecord”两张表,他们分别用来保存物品信息和物品的出入库记录信息,结构如下

uMateriel
----------------
mId   int
mName  nvarchar(40)
mNum   int DEFAULT 0

uRecord
----------------
rId   int
mId   int
rNum   int
rDate  datetime DEFAULT GetDate()
rMode  bit DEFAULT 0

好了,数据表已经有了,现在看一下实际的应用。

  现在,我们要购入物品A,数量100,时间为当天,已知物品A的编号为1,那么通常我们需要做以下两个步骤:

1、在 uRecord 记录表中增加一条物品A的购入记录:

  Insert INTO uRecord (mId, rNum, rMode) VALUES (1, 100, 0)

2、更新 uMateriel 物品库存表中物品A的数量:

  Update uMateriel SET mNum = mNum + 100 Where mId=1

也就是说代码中要先后处理以上两条语句,才能保证库存的准确性,以ASP代码为例:


On Error Resume Next
'// 设 adoConn 为已经连接的 ADODB.Connection 对象
With adoConn
        '// 事务开始,因为涉及到多步数据更新操作,所以在这里使用事务
        .BeginTrans
        '// 插入物品入库记录
        .Execute("Insert INTO uRecord (mId, rNum, rMode) VALUES (1, 100, 0)")
'// 更新物品库存记录
        .Execute("Update uMateriel SET mNum = mNum + 100 Where mId=1")
'// 判断是否产生了错误
        If Err.Number <> 0 Then
                '// 如果有错误,事务回滚
                .RollbackTrans
                Response.Write "错误!"
                Err.Clear
        Else
               '// 如果没有错误,则提交事务
                .CommitTrans
        End If
End With

以上代码可以更新一条入库记录了,但是我们今天要了解的是触发器的应用,那么要在触发器里写什么内容可以简化以上代码呢?下面来创建一个触发器。

  创建触发器的语法很长,简化为:

Create TRIGGER 触发器名 ON 表名/视图名
{ FOR | AFTER | INSTEAD OF } { [Delete] [,] [Insert] [,] [Update] }
AS
  触发器内容(SQL 语句)
SQL SERVER 联机丛书的描述:
AFTER

指定触发器只有在触发 SQL 语句中指定的所有操作都已成功执行后才激发。所有的引用级联操作和约束检查也必须成功完成后,才能执行此触发器。

如果仅指定 FOR 关键字,则 AFTER 是默认设置。

不能在视图上定义 AFTER 触发器。

INSTEAD OF

指定执行触发器而不是执行触发 SQL 语句,从而替代触发语句的操作。

在表或视图上,每个 Insert、Update 或 Delete 语句最多可以定义一个 INSTEAD OF 触发器。然而,可以在每个具有 INSTEAD OF 触发器的视图上定义视图。

INSTEAD OF 触发器不能在 WITH CHECK OPTION 的可更新视图上定义。如果向指定了 WITH CHECK OPTION 选项的可更新视图添加 INSTEAD OF 触发器,SQL Server 将产生一个错误。用户必须用 Alter VIEW 删除该选项后才能定义 INSTEAD OF 触发器。

{ [Delete] [,] [Insert] [,] [Update] }

是指定在表或视图上执行哪些数据修改语句时将激活触发器的关键字。必须至少指定一个选项。在触发器定义中允许使用以任意顺序组合的这些关键字。如果指定的选项多于一个,需用逗号分隔这些选项。

对于 INSTEAD OF 触发器,不允许在具有 ON Delete 级联操作引用关系的表上使用 Delete 选项。同样,也不允许在具有 ON Update 级联操作引用关系的表上使用 Update 选项。
现在根据上面的语法我们建立一个触发器(注意一点,触发器是附于一张表或视图的,所以只能在表里建立或在查询分析器里建立),这个触发器的功能就是自动更新库存数量


Create TRIGGER [trUpdateMaterielNum] ON [dbo].[uRecord] 
-- 表明在插入记录之后执行这个触发器
AFTER Insert
AS
-- 当前更新的编号
DECLARE @intID                int
-- 当前更新的数量
DECLARE @intNum        int
-- 当前模式
DECLARE @intMode        int
-- 判断是否有记录录被更新,@@ROWCOUNT是系统函数,返回受上一语句影响的行数。
IF @@ROWCOUNT >0
BEGIN
       -- 取得当前插入的物品编号和数量,Inserted 表用于存储 Insert 和 Update 语句所影响的行的副本。
        Select @intID=mId,@intNum=rNum,@intMode=rMode FROM Inserted
-- 判断当前模式(0为入库,1为出库)来更新当前物品的数量
        IF @intMode = 0
                Update uMateriel SET mNum = mNum + @intNum Where mId=@intID
        ELSE
                Update uMateriel SET mNum = mNum - @intNum Where mId=@intID
END

我们现在来了解一下这个触发器,首先使用 Create TRIGGER 语句定义一个基于 uRecord 表的触发器 trUpdateMaterielNum,AFTER Insert 表明这个触发器会在插入记录之后执行,也就是说当我们在程序里执行 Insert INTO uRecord (mId, rNum, rMode) VALUES (1, 100, 0) 这条语句之后,trUpdateMaterielNum这个触发器里的内容就会被自动执行,也就是说库存将会被自动更新了。现在我们更改一下ASP的代码


On Error Resume Next
'// 设 adoConn 为已经连接的 ADODB.Connection 对象
'// 插入物品入库记录
adoConn.Execute("Insert INTO uRecord (mId, rNum, rMode) VALUES (1, 100, 0)")
'// 判断是否产生了错误
If Err.Number <> 0 Then
        Response.Write "错误!"
        Err.Clear
End If

是不是简化了很多呢,是的,在这里已经不用考虑库存方面,只需要插入流水帐就可以了,库存更新就交由触发器来处理。

  以上的例子是触发器的其中一个应用,在触发器的参数中还有 Delete、Update,他们分别在删除和更新时或之后执行。下面看一个删除时的触发器例子。

  我们在数据库中增加一个表,用来记录日志,其结构如下

uSysLog
--------------
lId                int
lEvent        nvarchar(200)
lTime                datetime DEFAULT GetDate()

现在假设这张表是用来记录系统的日志用的,当我们删除一条流水帐时,往日志表里记录一条事件,那么我们来创建一个基于 uRecord 表的删除时的触发器


Create TRIGGER [trDeleteRecord] ON [dbo].[uRecord] 
-- 表明在插入记录之后执行这个触发器
FOR Delete
AS
-- 当前删除的流水号
DECLARE @intID                int
-- 当前删除的数量
DECLARE @intNum        int
-- 当前模式
DECLARE @intMode        int
-- 判断是否有记录录被更新,@@ROWCOUNT是系统函数,返回受上一语句影响的行数。
IF @@ROWCOUNT >0
BEGIN
        -- 取得当前删除的行信息,Deleted 表用于存储 Delete 和 Update 语句所影响的行的复本。
        Select @intID=rId,@intNum=rNum,@intMode=rMode FROM Deleted
-- 向日志表中插入一条简单的删除事件日志
        Insert INTO uSysLog (lEvent) VALUES ('用户删除了流水号为:' + CAST(@intID as nvarchar(20) + ',数量:' + CAST(@intNum as nvarchar(20) + ',方向:' + CASE @intMode WHEN 0 THEN '入库' ELSE '出库' END)
END

建立好触发器后,现在只要我们删除 uRecord 表中的一条记录,就会在系统日志中增加一条事件日志。

  通过以上简单的介绍,希望原来没有使用过触发器的朋友能对触发器有个大致的概念和印象,如果你要深入了解的话,SQL SERVER联机丛书就是你的好帮手,那么触发器的简单应用就介绍到这儿了。

0
投稿

猜你喜欢

  • 好多网友问起来,·深度学习网址导航·深度学习整站系统 的后台管理能否增加批量删除功能,如何加:就是列出N篇文章或网址信息,每篇文章或网址前有
  • 环境:RHEL 5.4 x86 , oracle 11.2 1.设定环境变量 在/home/oracle编辑 # .bash_profile
  • 我们在使用ASP 内置的ADO组件进行数据库编程时,通常是在脚本的开头打开一个连接,并在脚本的最后关闭它,但是就较大脚本而言,在多
  • Google Chrome 的发布,使我们更加的注重基于 WebKit 核心的浏览器的表现情况,但我们很多时候“不小心”就会出现问题。考虑下
  • 所有数据库和状态文件都包含在其中。但是,在确定数据目录内容的布局中管理员有某些职责。本文讨论为什么要移动数据目录的各个部分(甚至是字典本身)
  • 今天做站时碰到个小问题:ASP正则获取文章内容图片地址,现在将此方法的思路拿出来分享下:Function RegExp_Execu
  • ancestor:祖先adjacent:相邻algorithm:运算法则anonymous box:无名盒子。例: anonymous in
  • 常用字段类型bit(0和1),datetime,int,varchar,nvarchar(可能含有中文用nvarchar) Varchar,
  • 如何做一个可以让人家申请使用的计数器?    好了,我们来做一个与页面分离的计数器,是文本型的啦。这也很简单,
  • ASP,一种最先广泛的流行在WEB行业的编程语言。严格的说,ASP还算不上的编程语言。不过,因为微软的大力支持,ASP这一路,走得非常顺利。
  • 今天处理了一个日期选择器的ie和ff的兼容问题,本来这种情况就很难找错误,找了好久才把错误定位到js中创建元素的方法document.cre
  • 本程序属于一种特别的方法。使用范围比较有限,而且有一定的危险性。借鉴了asp后门里的一些方法。由于读取某IP的网卡MAC地址本程序通过调用a
  • SQL SERVER数据存储的形式在谈到几种不同的读取方式之前,首先要理解SQL SERVER数据存储的方式.SQL SERVER存储的最小
  • 当你要使用data URI scheme的时候,你会发现,虽然他可以使用在绝大多数浏览器上,但无法再IE6和IE7上工作。不过值得庆幸的这一
  • 一、“无”的哲学佛家讲究“因果报应”,有果必有应。此段看似与主题没有血缘关系,实际讲的是“因”。我个人比较喜欢老子的道家思想,并喜欢以其思想
  • 块级元素块级元素生成一个元素框,(默认地)它会填充其父级元素的内容,旁边不能有其他元素。换句话说,他在元素框之前和之后生成了“分隔”符。我们
  • asp之家注:本篇asp留言本教程可以说是我见过的最详细,写的最认真的,最适合初学者来学习asp的一篇教程。在此感谢作者hemooday。可
  • 如何用POP3接收电子邮件?POP3大行其道,我看见朋友已经用Jmail和POP3接收邮件了。该如何做?以Jmail4.1为例,我们演示一下
  • CSS Hack是在标准CSS没办法兼容各浏览器显示效果时才会用上的补救方法,在各浏览器厂商解析CSS没有达成一致前,我们只能用这样的方法来
  • 到了今天,数据库已经成了网站的灵魂,可以说,没有对数据进行集中管理就算不上是一个真正的网站。而ASP加数据库,更成了主流中的主流,网站里的用
手机版 网络编程 asp之家 www.aspxhome.com