关于复合触发器Before/After Statement部分作用的理解是否正确?
你的理解大部分都很到位,不过咱们可以再细化几个关键点,帮你把逻辑捋得更清晰:
关于BEFORE STATEMENT部分
你说的用来初始化不依赖:NEW/:OLD的变量完全正确!比如你示例里的v_date和v_user,这类触发器内的全局变量会在**整个触发事件(比如一次批量INSERT/UPDATE)**开始前只初始化一次,不用每行都重复获取SYSDATE或USER,能提升效率。而且这部分确实是在所有行处理之前执行,还没有行级数据产生,所以确实没法使用:NEW/:OLD,这点你抓得很准。
关于AFTER STATEMENT部分处理变异表错误
这个理解完全正确!变异表问题通常出在行级触发器里直接操作触发表(比如在UPDATE触发器里又SELECT触发表),因为此时表正处于DML执行的“变异”状态,数据库会阻止这类操作避免数据不一致。而复合触发器的AFTER STATEMENT部分是在整个DML语句执行完毕、表状态稳定后运行的,这时候再操作触发表就不会触发变异表错误了,很多场景下都会用这个部分来做这类后续处理。
关于“对应部分添加行评估前后的操作”
这点可以补充下细节:复合触发器除了语句级的BEFORE/AFTER STATEMENT,还有行级的BEFORE EACH ROW和AFTER EACH ROW部分。
- 如果是所有行处理前的统一操作(比如初始化全局变量),放在BEFORE STATEMENT没问题;
- 如果是每行处理前后的操作(比如给每行的创建时间、创建人赋值),就得放在对应的行级部分里——因为这类操作需要用到行级的
:NEW/:OLD变量,而语句级部分是拿不到这些行数据的。
你的示例代码格式整理后是这样的:
CREATE OR REPLACE TRIGGER zipcode_compound FOR INSERT OR UPDATE ON zipcode COMPOUND TRIGGER v_date DATE; v_user VARCHAR2 (30); BEFORE STATEMENT IS BEGIN v_date := SYSDATE; v_user := USER; END BEFORE STATEMENT; END zipcode_compound;
内容的提问来源于stack exchange,提问作者Zampanò
相关产品推荐
相关产品推荐

