鼎捷用户俱乐部

 找回密码
 注册
搜索
查看: 32854|回复: 115

关于 SQL 触发器 简单教程(一) [复制链接]

Rank: 3Rank: 3

荣誉
0 点
金币
1411 个
注册时间
2007-4-18
阅读权限
200
精华
1
积分
123
帖子
181
发表于 2007-11-3 14:05:29 |显示全部楼层
刚刚看到有人说触发器不是太明白,我在这里就班门弄斧的稍微谈谈自己的看法:% y+ B# @+ c$ t( [, s
先引用一段 关于触发器的说明(最好慢慢看完,如果这个说明你都不原意拜读,那我就没办法了),
* q  g: q9 `5 w! i- |% n9 r在针对易飞ERP中的触发器做几个举例说明。! _! ~: k# X/ ^  ~" f( [$ A
=============================================================================
( e) C: `1 Y8 Z/ w触发器是一种特殊的存储过程,类似于其它编程语言中的事件函数,SQL Server? 允许为 INSERT、UPDATE、DELETE 创建触发器,当在表(视图)中插入、更新、删除记录时,触发一个或一系列 T-SQL 语句。 (定义)( M  j. c/ T# @* E

4 Z) Y1 }+ I0 c5 eFOR CREATE TRIGGER 语句
& c' s" {$ e& M! sFOR 关键字之后可以跟 INSERT、UPDATE、DELETE 中的一个或多个,也就是说在其它情况下是不会触发触发器的, 包括 SELECT、TRUNCATE、WRITETEXT、UPDATETEXT。
; d2 N" `- Z+ C
: I0 M& o8 @( ~; X# wTRUNCATE TABLE 和不带 WHERE 的 DELETE 功能是一样的,都是删除表中的所有数据,不过 TRUNCATE TABLE 速度更快,占用的日志更少,这是因为 TRUNCATE TABLE 直接释放数据页并且在事务日志中也只记录数据页的释放,而 DELETE 是一行一行地删除,在事务日志中要记录每一条记录的删除。
/ s; u. ]- l1 P2 a  ?# x! D! s3 g# f9 y$ W
那么可不可以用 TRUNCATE TABLE 代替不带 WHERE 的 DELETE 呢?在以下情况是不行的:
( R8 a( p& j9 Q0 E: A! t$ t1、要保留标识的情况下不能用 TRUNCATE TABLE,因为 TRUNCATE TABLE 会重置标识。 8 Q1 w! G, J+ x! L; Z1 ]2 L* o+ W
2、需要使用触发器的情况下不能使用 TRUNCATE TABLE ,它不会激发触发器。
5 {2 v5 A, C, C6 G" v, q8 u0 K3、对于由 FOREIGN KEY 约束引用的表(即主键所在的表,不是外键所在的表)不能使用 TRUNCATE TABLE。 6 w$ m$ Y& w7 x/ _
4、对于参与了索引视图的表不能使用 TRUNCATE TABLE ,注意指索引视图,并非普通视图。
; k2 k0 o  {8 r5 l; h+ t
+ y  ~; h) k5 {* {" Z不能在触发器中使用的语句
9 Q+ [, Z3 e8 Y' V0 j. t. @' E) o4 R, [. I+ S9 D/ S5 Z$ x$ M
触发器中可以使用大多数 T-SQL 语句,但如下一些语句是不能在触发器中使用的。
, A3 `5 n" `2 N6 U6 h3 \CREATE 语句,如:CREATE DATABASE、CREATE TABLE、CREATE INDEX 等。 3 c/ Z4 |" P& @2 q
ALTER 语句,如:ALTER DATABASE、ALTER TABLE、ALTER INDEX 等。
% L  }: s' A+ w3 ADROP 语句,如:DROP DATABASE、DROP TABLE、DROP INDEX 等。
$ R  f5 p: o; H$ O( k1 G% h, ]DISK 语句,如:DISK INIT、DISK RESIZE。
: y0 m6 E" G& m. @7 B! hLOAD 语句,如:LOAD DATABASE、LOAD LOG。 * R% q1 ^) ]5 @) Z
RESTORE 语句,如:RESTORE DATABASE、RESTORE LOG。 3 |2 u5 y/ E  N1 _( U: ~
RECONFIGURE : K4 c( w3 p0 Y& z# ]( k5 Q! X5 D
说明:有人说不能用 TRUNCATE TABLE 语句,其实是可以的。 & n' F  V8 K% R4 L

1 g6 P( {0 N7 l# D! i  ]5 t, _# g8 p& L% u9 s7 V# V

% C2 G; g2 w1 Q0 [+ v查看某个触发器的内容 1 f% q/ q, Q) U

0 k* O& \# M! g, \use 数据库名
) i8 u$ S' U! ogo 3 ^. u7 @3 ~6 L' d/ Z
exec sp_helptext '触发器名称'
" w% S; b' u: v" ?" D将会以表的样式显示触发器内容。
5 ?, Z& Q; {" A" D, j. [  d除了触发器外,sp_helptext 还可以显示 规则、默认值、未加密的存储过程、用户定义函数、视图的文本 8 Z; ?' M6 H% F7 `, Q
用企业管理器查看
( s) N9 F# P7 m! @" Z$ ?( z; W8 W) G5 P0 s
或者在表上点右键->“所有任务”->“管理触发器”,选择所要查看的触发器 9 H1 ~$ U: @6 |) o& E
' O" n0 x; @7 |5 _0 q
查看当前数据库中有哪些触发器
% n% C( A  i4 W! Z2 @7 y1 Y2 h0 Y+ L( M
在查询分析器中运行: , C( l- l- W0 |" g8 a, P7 V

  \* }8 P7 T. R6 u3 i( vuse 数据库名 % m4 @, U* b% n0 j& E
go ' |% `0 _0 |2 L, o8 P
select * from sysobjects where xtype='TR'
& p# ~+ k) ^" H* n- c) q0 lsysobjects 保存着数据库的对象,其中 xtype 为 TR 的记录即为触发器对象。在 name 一列,我们可以看到触发器名称。 * I: e) [: w) h
6 a, b$ I6 c: M) w3 E2 {
删除触发器
7 J' a- k" u, _% z8 Y2 A: m4 @2 u2 e2 t( w
$ Y# g" h& S- C) F
用查询分析器删除
6 e3 H" M3 h2 x; X% M; r% s- V7 B在查询分析器中使用 drop trigger 触发器名称 来删除触发器。 : r3 V! P5 T0 `1 Q9 u
也可以同时删除多个触发器:drop trigger 触发器名称,触发器名称...
4 l4 Y; y9 S6 ~5 ]注意:触发器名称是不加引号的。在删除触发器之前可以先看一下触发器是否存在: 0 j0 t/ U$ |0 b6 _3 v: T9 o
if Exists(select name from sysobjects where name=触发器名称 and xtype='TR')
% w  L0 @8 a9 g& n% _$ L( F7 P3 ]2 |
用企业管理器删除
: j/ y! o1 W9 o# e: u3 T在企业管理器中,在表上点右键->“所有任务”->“管理触发器”,选中所要删除的触发器,然后点击“删除”。
# g4 a. v2 o" l  w
0 V1 w9 D3 ]: n" m
5 K2 w4 Y' }% u2 G- z重命名触发器
0 z. C$ y* G; H& u用查询分析器重命名
1 c% }- p2 b* Y/ ^' m' bexec sp_rename 原名称, 新名称 ! S  |' {% F4 s% r8 [
sp_rename 是 SQL Server? 自带的一个存储过程,用于更改当前数据库中用户创建的对象的名称,如表名、列表、索引名等。
' {5 l. h5 S2 ^9 k
& [( ^! ~8 F4 {. j用企业管理器重命名 3 j/ V7 S, \1 m- [& x) a* L" C3 ~
在表上点右键->“所有任务”->“管理触发器”,选中所要重命名的触发器,修改触发器语句中的触发器名称,点击“确定”。 / ^1 A: l9 p0 R5 }& k. G
$ g. t/ @# W2 y% T, G) {
查看触发器的属性
: ^( ^5 N+ u* s. V& \( C; c* _7 n% G
存储过程 sp_helptrigger 用于查看触发器的属性。
+ O% ]4 v  L/ ~+ U; W1 B+ O" `7 z
/ o4 s7 t0 W7 x2 |8 U' w& H" J2 Ysp_helptrigger 有两个参数:第一个参数为表名;第二个为触发器类型,为 char(6) 类型,可以是 INSERT、UPDATE、DELETE,如果省略则显示指定表中所有类型触发器的属性。
; |6 R# A  ~0 u6 K2 T
# `* I& ?9 n, i! u6 i* W例:
7 a# \$ M( Q' S) }% Q# V, ^8 M2 o# s0 u. W7 I
use 数据库名 ( w4 m- w- q$ S0 v9 s
go 1 Y+ U# s' U' _/ n: T, T8 ?8 `
exec sp_helptrigger tbl # q2 J! E, X8 l! D9 B# t
' E. H$ f3 c; Y4 o0 `, o  A8 _. A
触发器更多语法
) C3 V9 p% f+ R, L$ V" M4 @6 J- h! |& Y1 ?' Q- j1 f5 }
INSTEAD OF
9 Y  H- B" b& [+ o/ l执行触发器语句,但不执行触发触发器的 SQL 语句,比如试图删除一条记录时,将执行触发器指定的语句,此时不再执行 delete 语句。例:
% \9 V# l% {8 M/ \. F7 U/ G- Qcreate trigger f ! o" T3 n, P+ z* H4 v( {- p" d3 f6 }& u
on tbl
: N$ I: w8 d% g8 Y; i- R2 q; o5 |: W* N4 yinstead of delete - j9 Y+ A6 `5 b3 O  T# t- g
as
: D! c8 \( c( Y! O3 N  `) o) [+ Qinsert into Logs... % n! i! }/ ~, g9 k

2 ?  W7 U, C: i+ E: y: @! FIF UPDATE(列名)
( J2 d. T3 ^3 s# a! L; j7 C检查是否更新了某一列,用于 insert 或 update,不能用于 delete。例: 0 i: M0 T- i  p+ R) f) Y8 X
create trigger f 8 l4 k( X& e# Y4 Y3 g
on tbl
: y' E& }/ S2 J3 Tfor update ; C, R" d3 Q( k+ X$ I' H
as + a1 Y7 @7 S" P5 h0 I" u
if update(status) or update(title) 8 ~. t( V4 J2 n, U9 d# i7 g0 `: \2 r+ q
sql_statement --更新了 status 或 title 列
5 R: Y! ~- K$ N5 Y: W- W0 Y+ R& U0 R" f
inserted、deleted
, F; k2 B9 z+ q0 Q$ ?, e) L0 u这是两个虚拟表,inserted 保存的是 insert 或 update 之后所影响的记录形成的表,deleted 保存的是 delete 或 update 之前所影响的记录形成的表
。例:
) l4 a% W; R* Ccreate trigger tbl_delete
; e/ T: r0 C3 v: u5 j0 v$ ?on tbl
* W3 C; S6 L" ~for delete
; f7 G+ K- A% [3 t& \as 5 ]) k5 x4 y# h$ L: h3 S
declare @title varchar(200)
1 b0 }& X/ r8 D* Tselect @title=title from deleted ; |0 p) \2 N# `8 E1 v' {& H+ y/ ^/ E
insert into Logs(logContent) values('删除了 title 为:' + title + '的记录')
# ?  B' |) d; `- U2 U说明:如果向 inserted 或 deleted 虚拟表中取字段类型为 text、image 的字段值时,所取得的值将会是 null。
* D( E* Z1 T. [! B2 h/ }7 E! k! [  Y1 Q$ h5 R/ }/ s
慎用触发器
2 i- R1 h6 r, `5 V3 ?触发器功能强大,轻松可靠地实现许多复杂的功能,为什么又要慎用呢。 触发器本身没有过错,但由于我们的滥用会造成数据库及应用程序的维护困难。 $ X; X" B7 X* T  B8 O! Q
1 L, i( \, B: m; B
在数据库操作中,我们可以通过关系、触发器、存储过程、应用程序等来实现数据操作,比如删除 T1 表记录时期望删除 T2 表相关的记录,此时可以建立级联删除的关系,也可以为 T1 表建立触发器使同时删除 T2 表相关记录,也可以自定义存储过程删除 T1 和 T2 表的记录,也可以在应用程序中使用两个 SQL 语句来删除……到底用哪一种好呢,应该说我们建立通过建立关系来实现级联删除是最好的,除非更有高的需求。
1 I9 P" [; ~$ O- K* Z
7 U, ^8 E4 Q; Z7 k7 ?触发器还有一个用途可以用来保障数据的完整性,但同时规则、约束、默认值也可以保障数据完整性,到底哪一个好呢,一般说来,较为简单的完整性要求我们不应该使用触发器。两者在运行机制上也是有区别的,像规则、约束、默认值这些是在数据更改之前进行数据验证,而触发器是在数据更改之后进行验证(如果事务回滚,该表将不会产生变化)。
- I! n3 i1 F( u5 Y; ]" b0 P/ f7 y9 I
总之,如果我们对触发器过分的依赖,就会造成遍地是程序的情况,因为触发器本身就需要别的程序给它一个触发条件,也就是说至少在两个地方存在着程序,同时我们抛弃了约束、默认值等而选用触发器,势必影响数据库的结构。
: T3 E/ Q! V# @5 c7 |0 r; j  ^, ]  T=============================================================================
4 I! i. `/ b. [, y0 u上面重点的部分我加了红色的标示。/ Y, X+ K, @) `2 \: [! N! D6 T! B! j
/ L, Z* D* `8 k  D
具体到我们用的易飞ERP其实也不是难事:; E4 c8 s& V' B: K. y, ]
随便举个例子:! N/ _2 K/ U! I) ^
例:我希望用户在新增品号信息的同时,把这个品号的品名(MB002)更新到商品描述(MB009)字段当中。3 b& F$ T- n; N' s( r3 _* c
CREATE TRIGGER MB009_Insert   --MB009_Insert 触发器的名称# V3 X* Z6 P+ N+ c+ D! M& D
ON [INVMB]                    --INVMB 数据表
8 W! `, D4 B( J, d: v) {FOR INSERT                    --关于INSERT 啥意思看上面的说明 :)
5 |# x' s% R2 u) ^/ SAS
. Z) h( x( m3 r' h9 L7 EDECLARE @MB001 VARCHAR(20)    --定义变量
$ w' b5 e! ?& [3 IUPDATE INVMB SET              % j6 x" g' G5 D) o8 }" _& @, y
MB009 = INVMB.MB002 % e: f  O. K! y2 Y* V, J5 ]( {
FROM INVMB INNER JOIN INSERTED --INSERTED 啥意思在上面说明里面也写的很清楚了 我不再熬述
; d4 X+ h* _/ k: ?; d, zON INVMB.MB001=INSERTED.MB001" s; Z% U" y4 @8 `3 F& s
4 k' S/ _, V% @# m
其他的也都是大同小异,会不会关键是看自己愿不愿意学了。
: L6 Y1 N6 A* F/ a! G8 J3 v  K" b
( T' v% e) u2 F' d5 E[ 本帖最后由 sunyesy 于 2007-11-3 14:20 编辑 ]
4

查看全部评分

Rank: 3Rank: 3

荣誉
0 点
金币
1411 个
注册时间
2007-4-18
阅读权限
200
精华
1
积分
123
帖子
181
发表于 2007-11-3 14:18:25 |显示全部楼层
补充一点有的人也许会问这段触发器如何使用? ( c! o' @& P* K0 u, |1 a! P0 v% T
其实你只要在查询分析器当中运行以后,在进入系统新增一个品号你就会发现,商品描述字段在你保存(insert)品号的时候被赋值了(MB002)。
  ~5 p. @6 D7 }7 G2 v, M' y或者打开企业管理器,选择表(INVMB) 点右键->“所有任务”->“管理触发器” 默认带出的是新建触发器 你点旁边的小箭头就看到刚刚新建的这个了。
2 m# X: C# _% k6 U& L3 c========================================================
; T9 g0 V$ y. c1 J( \4 b, S; u说的够直白了吧,如果还不会,干脆拖出去喂狗吧 (呵呵 玩笑一下,希望能給初学者带来一点点帮助,老手就不用看了)4 [/ w* m/ M" H
5 A4 y) _0 R( L1 J  q
[ 本帖最后由 sunyesy 于 2007-11-3 14:20 编辑 ]

使用道具 举报

Rank: 3Rank: 3

荣誉
0 点
金币
124 个
注册时间
2007-6-22
阅读权限
200
精华
0
积分
110
帖子
220
发表于 2007-11-7 11:58:43 |显示全部楼层
呵呵!这个对新手来说是最好的学习资料了~~: v- x7 I; |4 v- t2 x$ i! f
昨天刚弄了个“客户订单显示产品单重”的问题,和楼主写的有异曲同工之处,呵呵~~go_exciting_end go_grimace_end

使用道具 举报

Rank: 7Rank: 7Rank: 7

荣誉
340 点
金币
1573 个
注册时间
2006-6-21
阅读权限
200
精华
1
积分
682
帖子
639
发表于 2007-11-7 16:17:32 |显示全部楼层
写的不错~
逝水流年
广告:供应SSL VPN设备、中高端路由器、防火墙

使用道具 举报

Rank: 1

荣誉
0 点
金币
143 个
注册时间
2006-1-20
阅读权限
200
精华
0
积分
75
帖子
149
发表于 2007-11-10 11:30:01 |显示全部楼层
great!go_bad_smile_end

使用道具 举报

Rank: 7Rank: 7Rank: 7

荣誉
9 点
金币
1550 个
注册时间
2006-7-16
阅读权限
200
精华
10
积分
508
帖子
800
发表于 2007-11-10 12:37:17 |显示全部楼层
go_amazing(1)_end go_exciting_end
福州小兵
QQ 4750103
Mail swgame@sohu.com
微博 http://t.qq.com/swgame

使用道具 举报

Rank: 3Rank: 3

荣誉
0 点
金币
248 个
注册时间
2006-10-11
阅读权限
200
精华
3
积分
166
帖子
266
发表于 2007-11-12 13:10:27 |显示全部楼层
学习
空头,多头都能赚钱,唯有贪心不能赚。市场不过是一场心理战术的较量!勇者胜,畏者败

使用道具 举报

Rank: 1

荣誉
0 点
金币
128 个
注册时间
2007-2-22
阅读权限
200
精华
0
积分
36
帖子
72
发表于 2007-11-20 09:29:04 |显示全部楼层
太好了,我一直在考虑应用触发器进行异常数据监控,好好拜读一下

使用道具 举报

Rank: 1

荣誉
0 点
金币
223 个
注册时间
2006-6-20
阅读权限
200
精华
0
积分
87
帖子
133
发表于 2007-11-24 09:23:30 |显示全部楼层

回复 1# 的帖子

http://bbs.dcmsclub.com/viewthre ... e%3D1&frombbs=1% U! \! J3 b& D
兄弟能帮帮忙看看吗!!!

使用道具 举报

Rank: 1

荣誉
0 点
金币
223 个
注册时间
2006-6-20
阅读权限
200
精华
0
积分
87
帖子
133
发表于 2007-11-25 10:03:41 |显示全部楼层
老兄!还是那问题!!!http://bbs.dcmsclub.com/viewthread.php?tid=9951我按照你的提示编写的结果语法错误,我想请教一下!!!由于其是一张批次单据产生多张工单!!!这时判断语句就有两个了,一个是批次计划相等,还有一个是品号得相等,这时怎么办?????谢谢!@!!!

使用道具 举报

Rank: 3Rank: 3

荣誉
0 点
金币
108 个
注册时间
2007-9-28
阅读权限
200
精华
0
积分
138
帖子
272
发表于 2007-12-5 13:27:21 |显示全部楼层
写的不错,正想学呢

使用道具 举报

Rank: 1

荣誉
0 点
金币
112 个
注册时间
2007-8-6
阅读权限
200
精华
0
积分
12
帖子
23
发表于 2007-12-6 21:56:21 |显示全部楼层
帮助还是不小啊,谢谢分享啊

使用道具 举报

Rank: 3Rank: 3

荣誉
0 点
金币
163 个
注册时间
2007-6-29
阅读权限
200
精华
3
积分
185
帖子
250
发表于 2007-12-19 15:11:13 |显示全部楼层
非常感谢,学习中。。。。。。。。

使用道具 举报

Rank: 1

荣誉
0 点
金币
102 个
注册时间
2007-6-28
阅读权限
200
精华
0
积分
27
帖子
54
发表于 2007-12-21 15:11:49 |显示全部楼层
谢谢

使用道具 举报

Rank: 8Rank: 8

荣誉
9 点
金币
493 个
注册时间
2006-3-31
阅读权限
255
精华
0
积分
341
帖子
629
发表于 2008-1-23 16:05:24 |显示全部楼层
支持!!
四方漫步,偶尔停泊!停下来当然来灌水!
http://www.dcmsclub.com/index.php?fromuid=528

使用道具 举报

Rank: 3Rank: 3

荣誉
0 点
金币
108 个
注册时间
2007-9-28
阅读权限
200
精华
0
积分
138
帖子
272
发表于 2008-1-27 09:08:11 |显示全部楼层
不错

使用道具 举报

Rank: 3Rank: 3

荣誉
0 点
金币
108 个
注册时间
2007-9-28
阅读权限
200
精华
0
积分
138
帖子
272
发表于 2008-1-27 09:09:09 |显示全部楼层
看过,写的确实不错

使用道具 举报

荣誉
0 点
金币
108 个
注册时间
2008-2-2
阅读权限
200
精华
0
积分
5
帖子
7
发表于 2008-2-2 08:23:04 |显示全部楼层
最近正在研究这方面的东东,谢谢楼主!

使用道具 举报

荣誉
0 点
金币
673 个
注册时间
2006-6-16
阅读权限
255
精华
2
积分
137
帖子
254
发表于 2008-2-19 09:14:57 |显示全部楼层
抢个位子,坐下慢慢看!

使用道具 举报

荣誉
0 点
金币
101 个
注册时间
2008-1-22
阅读权限
200
精华
0
积分
8
帖子
14
发表于 2008-2-19 10:31:27 |显示全部楼层
简单描叙一下我的看法 触发器是地雷存储过程是炸弹 所以你触发了地雷才爆炸 ,而炸弹 要你发射才爆炸的呵呵

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

Archiver|鼎捷用户俱乐部 ( 粤ICP备05003032号 )

GMT+8, 2012-2-11 20:55

Powered by Discuz! X2 Licensed

© 2001-2011 Comsenz Inc.

回顶部