关于触发器在行级和语句级的执行顺序问题

本文详细介绍了Oracle数据库中触发器的概念及不同类型,包括行级触发器、语句级触发器、BEFORE和AFTER触发器等,并通过具体示例演示了各种触发器的执行顺序。

原创于2008年01月30日,2009年10月18日迁移至此。


原来总是对触发器的几种写法和执行先后顺序感到困惑,找了个时间把Oracle的官方文档看了一下,然后做了几个例子,终于有点明白了。:
Types of Triggers
触发器类型
Row Triggers and Statement Triggers
行级触发器和语句级触发器
BEFORE and AFTER Triggers
BEFORE和AFTER触发器
INSTEAD OF Triggers
INSTEAD OF触发器
Triggers on System Events and User Events
系统事件和用户事件触发器
--后面两种暂时不讨论
Trigger Type Combinations
组合触发器类型
Using the options listed previously, you can create four types of row and statement triggers:
根据前面所列的选项,我们能够创建四种类型的行级和语句级触发器
BEFORE statement trigger
BEFORE 语句级触发器
Before executing the triggering statement, the trigger action is run.
执行触发SQL 语句之前,就会激活触发器动作。
BEFORE row trigger
BEFORE 行级触发器
Before modifying each row affected by the triggering statement and before checking appropriate integrity constraints, the trigger action is run, if the trigger restriction was not violated.
在修改由触发SQL语句影响的每一行记录之前或者在检查完整性约束之前,将会执行触发动作。
AFTER row trigger
AFTER 行级触发器
After modifying each row affected by the triggering statement and possibly applying appropriate integrity constraints, the trigger action is run for the current row provided the trigger restriction was not violated. Unlike BEFORE row triggers, AFTER row triggers lock rows.
在修改由触发SQL语句影响的每一行记录之后或者在满足完整性约束之后,将会执行触发动作。和BEFORE行级触发器不同,AFTER行级触发器将会锁定记录。
AFTER statement trigger
AFTER 语句级触发器
After executing the triggering statement and applying any deferred integrity constraints, the trigger action is run.
在执行完毕触发SQL语句之后和确保不违反完整性约束的情况下,将会执行该触发动作。
1. 创建一张数据表和一张记录触发动作的表,再创建一个序列用来记录各个触发器触发动作的先后顺序。
CREATE TABLE test
(
  TestID    INTEGER NOT NULL,
  TestName  VARCHAR2(20) NOT NULL,
  CreateDT  DATE,
  UpdateDT  DATE
);
ALTER TABLE test ADD CONSTRAINT TestPrimaryKey PRIMARY KEY (TestID);
CREATE TABLE TriggerLog
(
  SeqID        NUMBER(20,0),
  TriggerName  VARCHAR2(50),
  TableName    VARCHAR2(30),
  FieldName    VARCHAR2(30),
  FieldValue   VARCHAR2(30),
  OperateOrder VARCHAR2(30),
  OperateType  VARCHAR2(30),
  OperateDT    DATE
);
-- Create sequence
CREATE SEQUENCE SeqTriggerLog
MINVALUE 1
MAXVALUE 100000
START WITH 1
INCREMENT BY 1;
2. 创建4个触发器,分别为前置后置行级语句级的组合
CREATE OR REPLACE TRIGGER TrgBefInsStateOnTest
  BEFORE INSERT ON test  
BEGIN
  INSERT INTO TriggerLog VALUES
    (SeqTriggerLog.NextVal,'TrgBefInsStateOnTest','test','TestName',' ','BEFORE','INSERT',SYSDATE);
END TrgBefInsStateOnTest;
--在Before行级语句上可以对受影响的记录进行预处理
CREATE OR REPLACE TRIGGER TrgBefInsRowOnTest
  BEFORE INSERT ON test  
  FOR EACH ROW BEGIN
    :new.CreateDT:=SYSDATE;
    INSERT INTO TriggerLog VALUES
      (SeqTriggerLog.NextVal,'TrgBefInsRowOnTest','test','TestName',:new.TestName,'BEFORE','INSERT',SYSDATE);
  END TrgBefInsRowOnTest;
--在After行级语句上可以进行相关完整性数据维护,当然对UPDATE更明显一些
CREATE OR REPLACE TRIGGER TrgAftInsRowOnTest
  AFTER INSERT ON test  
  FOR EACH ROW BEGIN
    INSERT INTO TriggerLog VALUES
      (SeqTriggerLog.NextVal,'TrgAftInsRowOnTest','test','TestName',:new.TestName,'AFTER','INSERT',SYSDATE);
  END TrgAftInsRowOnTest;
CREATE OR REPLACE TRIGGER TrgAftInsStateOnTest
  AFTER INSERT ON test  
BEGIN
  INSERT INTO TriggerLog VALUES
    (SeqTriggerLog.NextVal,'TrgAftInsStateOnTest','test','TestName',' ','AFTER','INSERT',SYSDATE);
END TrgAftInsStateOnTest;
3. 首先一次性插入多条记录,然后分别单独插入两条记录,看看其运行的先后
INSERT INTO test(testid,testname) SELECT column_id,column_name FROM user_tab_columns WHERE table_name='TEST';  
COMMIT;
INSERT INTO test(testid,testname) VALUES(5,'AAA');
INSERT INTO test(testid,testname) VALUES(6,'BBB');
COMMIT;
SELECT * FROM test;
SELECT * FROM TriggerLog;

最终执行触发器的先后顺序如下
1. 首先执行Before Insert State触发器,每条语句仅执行一次
2. 其次执行Before Insert Row触发器,为SQL语句影响的记录数的多少
3. 再次执行After Insert Row触发器,为SQL语句影响的记录数的多少
4. 最后执行After Insert State触发器,每条语句仅执行一次
ITPUB个人空间�T's6q @u-W2n#e ITPUB个人空间"Qn{-O�GW"`@ ITPUB个人空间)T8t G5t^C-F+] "X7N(N:/B%A%y8cs6517 (Gy%b6JK-v9B8_jJ6517 L HV#DdvH6517 ITPUB个人空间}oau-kd"|*Tq 0qd3_mT:t3f6517 ITPUB个人空间hmM&J7E*Y7q+r-j 7xo)wia${6517 ITPUB个人空间sKua5O /X7b3u ITPUB个人空间8HP9Dqx)^*]Xm+A QGf U6n"[6517 ITPUB个人空间�K4i3@3j Y#[ ITPUB个人空间"d�p2I3@_ ITPUB个人空间XBwDa :Ju$| @]OQ.Q6517 ITPUB个人空间hr l$](t`` ITPUB个人空间`"}Pd~| ITPUB个人空间8eUWH$M*PJ U4f|:e)D6517 g2T e4{w{;R6517 ITPUB个人空间{&a6Y(bVn-Y ITPUB个人空间8F/o9z2^rO+E ITPUB个人空间�/g_'Zv4N 3gp*ST c;U6517 -ED'm3? s7cX1R6517 ITPUB个人空间T%h6b8d B| ITPUB个人空间/?w&QAWT"ut ITPUB个人空间s2F._k#Ux^+W G?/(~ E F-S7w,C6517 ITPUB个人空间7tvM:Cm`k y/a ITPUB个人空间~IZ[dRA] ITPUB个人空间({�^2}I6lx/l |x~suA*i,l6517 j-V/E `9J*T)JE6517 j:_p }pg(_B6517 ,DIc6eD)na�j6517 @"c5Nx(F6517 ~4j^e,I2u6517 GhP1aEG)U1n.sa6517 J$_ dp R%d0Y6517 bJ?;/)_0[zl/p3t6517 +Dhi8la(Xr f/J3hl5P6517 +I,T9S?r5z)Z;w6517 |P D%cA.R@%Z6517 ITPUB个人空间,C:a*O,v3u^.[#L QoC*Kx1}8G$d_6517 ITPUB个人空间%Nz*k�Ag'y/7z| h(y3r6P$P*E6517 D!b)x? vk1v6517 ITPUB个人空间Y./o3V.Zyg +VnX @8fY1D6517 'm"Q /4[d*B/#b X3p6517 ITPUB个人空间0ys8@w1K+d!_%[~f ITPUB个人空间 PQ.ux{ @:X(H&c8X y[*RLdU Fk6517 ITPUB个人空间"}&O$}2@}W$~ ITPUB个人空间9`FI e)^)_8s(Z ITPUB个人空间*jd sNx5xbT ITPUB个人空间x Q1d�i[ ITPUB个人空间5C2Z;I#WB�n ITPUB个人空间9e.^1whV/ ITPUB个人空间A4qm]f/0w ITPUB个人空间_L i8f"|k B$Gj ITPUB个人空间!a ZK�A(G *ANi ])G1D*d6517 ITPUB个人空间_z/N*m[_'k ITPUB个人空间fg,i6h)/4I+O&_^ Y ITPUB个人空间 y:RM5e!V;s'c eaHPNA5b6517 7jM%L,|.pCb,b&L6517 ITPUB个人空间4?�~'ab2t;|? ITPUB个人空间(`j h /(q_Dd 9@X+c{0R p)T`nN6517 ITPUB个人空间|[Kw/? 1wcLx,RFdL6517 7@]JHeK6517 k0BJ9L.ae2~-p)KJ4S6517 te&vEF/6517 H-vK5k JF5t0B6517 %RXj$qqL o._6517 apAi9H,Y-kx6517 f;tzi [6517 ITPUB个人空间"OpY/N@V%v ZBO0H;b n6517 o*~ y+B [^6517 a*P_wgN t6517 ~:I(W;D%@ w!H6517 2U"W M�YEr&vo6517 2rI+RM@*gd5Z,lH6517 d0Sp-PPB6Uj6517 ITPUB个人空间/$EB-F {#{0H T ITPUB个人空间? A)Ic Ynr C;H V ITPUB个人空间 {3r2e7iV W 8cqnY"n+R//r6517 ITPUB个人空间_�Y;L Bb9iq ITPUB个人空间 l _ Tf]5zr-VIF ITPUB个人空间 N3MW9JN4dL"_~4b!g

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

python与大数据分析

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值