回答

收藏

创建用于插入,修改和删除的数据库触发器的正确??语法是什么

技术问答 技术问答 230 人阅读 | 0 人回复 | 2023-09-14

我在SQL Server中有一个数据库触发器的基本情况,但遇到了问题。* Q% t$ V1 q4 A
我有表 Users (标识,名称,电话等),并且我有表 UsersHistory (标识,user_id操作,字段,时间戳)
1 U. g' l4 ?3 h2 h# }* |; g8 F4 A我想要一个数据库触发器,随时可以将其插入,更新或删除到用户中,我希望在UsersHistory中创建一个具有用户ID和已完成操作的新记录(插入新的,更新的字段,已删除的ID。基本上是审计日志表。
' V: a. U" {9 d& B9 F, e1 g3 M6 c这是我走了多远,但我不知道如何:" V* K8 t8 s0 D" {' L! A
[ol]获取有关修改和删除的ID,以及) N' W, i& j/ ^# ~
如何获取已更改字段和已执行操作(插入,删除,更新)的列表5 ]2 ~+ t) w# z2 V; j
[/ol]) N9 f" Q! h1 h& Z
CREATE TRIGGER Update_Users_History
: T  K3 c5 t: c& K   ON  Users
0 [5 N' q: ^7 ]" ]6 c! r   AFTER INSERT,DELETE,UPDATE
& ?# I4 M( h" L& U0 \ AS
  p: \, F! I, c$ v BEGIN
7 N: ]5 W) W. ^6 F4 F/ H-- Insert statements for trigger here- T5 C8 m! I7 ?( f
insert into UsersHistory (user_id, [action], [fields], timestamp)  m; H! X1 \, ]
select  max(id) as user_id, {action ??},{fields??}  getdate() from Users)# N8 y- P) X5 F; }" z2 }. A
END
2 G; R& d& b1 y! wGO
$ b9 w7 _+ o4 C9 _( j2 z1 G5 Y有什么建议?
8 y- |( `, A1 K3 @3 a' \2 m                / m" K3 |3 H4 f
解决方案:
+ f* h5 C0 ^0 T8 ^; K! u, @               
" `* H; h2 S5 U0 k+ r
. C: @- H- j" Z* ]- N2 `5 J
# q" i3 C! S$ q6 h+ D7 {/ o                最简单的方法可能只是简单地创建三个触发器-每个操作一个:
# |) X7 v3 i! Z7 ^- wCREATE TRIGGER trgUserInsert  u7 R! D+ U% L, L9 q. ~
ON dbo.User AFTER INSERT
2 w0 T5 u) u& ]3 R1 w7 C' FAS BEGIN+ A6 P3 v( x( \0 c& s
   INSERT INTO dbo.UserHistory............
9 d: ^! f% O# w2 K2 ]& P/ A% V6 m! e1 pEND
( }) p0 C! Q4 M8 `# vCREATE TRIGGER trgUserDelete" S/ R2 S3 {" ^7 n  s' H
ON dbo.User AFTER DELETE
$ D% g  [! c4 L9 [! ~* x4 B- \; vAS BEGIN
! [% S3 R1 u6 X% X   INSERT INTO dbo.UserHistory............
5 ]1 [( ]! Y! y! m  n& e& e6 nEND7 X* }" X, n5 Q8 M# x
CREATE TRIGGER trgUserUpdate
# n% o+ {, I8 g" V2 s7 `0 `ON dbo.User AFTER UPDATE
" n6 `1 ?9 @+ O; BAS BEGIN2 p  I. O. E+ r1 ~8 _
   INSERT INTO dbo.UserHistory............- ]* Y2 C8 e$ F" d
END
5 j1 T) d% ?/ I9 F, O. W( k* u这样,事情就很简单,您可以轻松地了解自己在做什么,如果您需要插入或删除大量项目,它还可以关闭单个操作的触发器。# r3 x: n& o2 E, s  @+ N  h/ S% `( A
在触发器内部,您有两个“伪表”-
1 Y$ a2 r* G& U8 R4 ]( aInserted(用于INSERT和UPDATE)和Deleted(用于UPDATE和DELETE)。这些伪表包含新插入值(或UPDATE中更新的值)的值,或已删除(对于DELETE)或已更新的值(对于UPDATE操作,在更新之前的旧值)的值。# T# E8 ^* r! x. R2 u: \# ~- P
你需要知道,如果你更新行,如数量庞大的触发将有一次甚至被称为Inserted以及Deleted通常包含多个行。
8 _$ b: T+ H  T& }0 O2 L作为示例,您可以像这样编写“ AFTER INSERT”触发器(只是猜测您的表结构可能是…。):6 j  E7 {: `9 {3 m3 x/ I
CREATE TRIGGER trgUserInsert  l# Z1 \1 z5 x) U
ON dbo.User AFTER INSERT0 [( F4 F+ m2 ~- A: }
AS BEGIN
8 U1 {5 I4 _) K   INSERT INTO ! y% |! z1 j0 s# Q
      dbo.UserHistory(UserID, Action, DateTimeStamp, AuditMessage)! i) _  C  V1 A( q
      SELECT % [2 P' f6 ^; |; K' c9 m8 z4 k! _+ E
         i.UserID, 'INSERT', getdate(), 'User inserted into table'
9 B$ I1 ^$ A8 b      FROM
& H2 m& _8 m/ M/ B4 Y9 K) \! e. A( V         Inserted i3 n. I, q* e) @0 ^( T) d6 [
END
! K* o- y0 f& v* G' P# I( V您正在寻找一种方法来找出此触发器引起的“动作”吗?我看不到有任何方法可以做到,这是将三个触发器分开的另一个原因。找出这一点的唯一方法是对Inserted和Updated表中的行进行计数:. O) d/ |% T- y. e+ J/ |; p
如果两个计数都大于零,则为 UPDATE
2 ]( v$ q# j3 {& R8 ^- z如果Inserted表中有行,但表Deleted中没有,则为INSERT
. t) p+ Y4 A! l如果Inserted表没有行,但是有Deleted,那是一个DELETE
. y' ^; u" }6 o  A& X
$ W7 u; X" x2 D* T- t. ?  J
您还正在寻找“已更新的字段列表”-再次,您实际上将没有任何简单的解决方案。您可以只浏览“用户”表中感兴趣的字段,然后检查* z# s" R, V& E' L  ~4 w8 t7 U4 c
IF UPDATE(fieldname) ......
2 G5 ?4 w6 N  ?$ T但这有点乏味。
: f2 r: W3 }; E或者,您可以使用该COLUMNS_UPDATED()函数-3 w8 O$ V; X8 b2 {; b) t. U4 S9 o
但是,该函数不能为您提供很好的列名列表,而是一个VARBINARY,其中每个列基本上都是一位,并且如果打开了该列,则该列也将被更新。不是很容易使用.....- n4 y2 D: o: l/ H, o9 f
# T- X0 F( E# @
如果您确实要创建一个大型触发器,则可以以此为基础-它检测导致触发器触发的操作,并将条目插入到User_History表中:
8 l: \* l& z) _4 H# JCREATE TRIGGER trgUser_Universal
9 X, n0 }3 S. v0 D3 y' XON dbo.Users$ ]) X/ ]) M1 U9 A
AFTER INSERT, UPDATE, DELETE
; X9 i1 t% E  ]$ i, oAS BEGIN* Q: J2 t0 ?: G+ |3 i/ _4 ]
  DECLARE @InsHasRows BIT = 0
* E) c) C. q  Z6 ]: I- G* e  DECLARE @DelHasRows BIT = 0
/ v8 U* N  }9 J' e. t% @9 W  IF EXISTS(SELECT TOP 1 * FROM INSERTED)8 r$ A2 I# Y' m8 M, K9 I, A
    SET @InsHasRows = 1
! T! }/ p) _5 @" F  z! i" u  ~  IF EXISTS(SELECT TOP 1 * FROM DELETED)! {. k6 h, L  s
    SET @DelHasRows = 1
7 ]# [  N( F# S$ l  DECLARE @TriggerAction VARCHAR(20)
) s7 c5 V6 Q8 w, z7 g  IF @InsHasRows = 1 AND @DelHasRows = 1
/ ?0 X3 w, {9 f8 D2 Z# W+ ~     SET @TriggerAction = 'UPDATE'
; X8 [; t$ m9 t' X7 G  ELSE2 U( b- f% V9 s7 b8 X8 v5 U/ r
     IF @InsHasRows = 1
( [9 _3 {; q+ H' O) L0 V% ]        SET @TriggerAction = 'INSERT'
7 |6 U0 K2 R& f% G* c7 c- a     ELSE  % K9 [& B1 O4 ^+ \" d' ?& J
        SET @TriggerAction = 'DELETE'
) ~6 W* L" G$ N% @  IF @InsHasRows = 1# {9 f: [4 O. r8 c0 d
    INSERT INTO dbo.UsersHistory(user_id, [action], [fields], timestamp)1 W- @% p  v) k( S1 d0 j
      SELECT i.UserId, @TriggerAction, null, getdate()
; \  J4 {6 f0 H      FROM INSERTED i
7 Y9 b( ]$ @- e7 @; R  ELSE  : n  n' x+ C5 Q
    INSERT INTO dbo.UsersHistory(user_id, [action], [fields], timestamp)
0 I2 H, O6 G: o4 n* A6 p3 _      SELECT d.UserId, @TriggerAction, null, getdate()
9 y' K7 H. I# S& L+ E* P      FROM DELETED d
6 b- q- Y8 T! R, S) b  }END
# M. R* H- Y% i) r5 b6 h我还没有弄清楚哪些字段已经更新过了-留给读者练习:-)" m- ?  F! A9 g3 F, g0 n! h

5 V; k* M# Q1 W) l- i这些帮助有用?
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则