复合触发器有问题。 :当指定部分之后的部分时,new.value在每行部分之前的中为空/空。
创建表格部分:
DROP TABLE test_tab;
CREATE TABLE test_tab
( ID_TEST_TAB NUMBER
);
INSERT INTO test_tab VALUES
(1
);
INSERT INTO test_tab VALUES
(2
);
触发器的部分:
CREATE OR REPLACE TRIGGER TEST_COMP_TRIGGER
FOR UPDATE ON test_tab
COMPOUND TRIGGER
---
BEFORE EACH ROW
IS
BEGIN
dbms_output.put_line('TEST_COMP_TRIGGER: BEFORE EACH ROW');
dbms_output.put_line('>>>> old: ' || :old.ID_TEST_TAB );
dbms_output.put_line('>>>> new: ' || :new.ID_TEST_TAB );
NULL;
END BEFORE EACH ROW;
---
AFTER STATEMENT
IS
BEGIN
NULL;
END AFTER STATEMENT;
END TEST_COMP_TRIGGER;
/
后:
UPDATE test_tab SET test_tab.ID_TEST_TAB=test_tab.ID_TEST_TAB;
我明白了:
TEST_COMP_TRIGGER: BEFORE EACH ROW
>>>> old: 1
>>>> new:
TEST_COMP_TRIGGER: BEFORE EACH ROW
>>>> old: 2
>>>> new:
如果省略之后的部分,结果是正确的:
CREATE OR REPLACE TRIGGER TEST_COMP_TRIGGER
FOR UPDATE ON test_tab
COMPOUND TRIGGER
---
BEFORE EACH ROW
IS
BEGIN
dbms_output.put_line('TEST_COMP_TRIGGER: BEFORE EACH ROW');
dbms_output.put_line('>>>> old: ' || :old.ID_TEST_TAB );
dbms_output.put_line('>>>> new: ' || :new.ID_TEST_TAB );
NULL;
END BEFORE EACH ROW;
END TEST_COMP_TRIGGER;
/
后:
UPDATE test_tab SET test_tab.ID_TEST_TAB=test_tab.ID_TEST_TAB;
我明白了:
TEST_COMP_TRIGGER: BEFORE EACH ROW
>>>> old: 1
>>>> new: 2
TEST_COMP_TRIGGER: BEFORE EACH ROW
>>>> old: 2
>>>> new: 2
为什么在第一种情况下:new.value是空白的?
-----------更新 我按照你的指示: 代码:
create or replace trigger TEST_COMP_TRIGGER
FOR UPDATE ON test_tab
COMPOUND TRIGGER
---- BEFORE
BEFORE STATEMENT
IS
BEGIN
dbms_output.put_line('TEST_COMP_TRIGGER: BEFORE STATEMENT');
NULL;
END BEFORE STATEMENT;
---- AFTER
AFTER STATEMENT IS
BEGIN
dbms_output.put_line('TEST_COMP_TRIGGER: AFTER STATEMENT');
NULL;
END AFTER STATEMENT;
---- BEFORE EACH
BEFORE EACH ROW IS
BEGIN
dbms_output.put_line('TEST_COMP_TRIGGER: BEFORE EACH ROW');
dbms_output.put_line('>>>> old: ' || :old.ID_TEST_TAB );
dbms_output.put_line('>>>> new: ' || :new.ID_TEST_TAB );
NULL;
END BEFORE EACH ROW;
END TEST_COMP_TRIGGER;
/
-----
SET serveroutput ON format wraped;
UPDATE test_tab SET test_tab.ID_TEST_TAB=test_tab.ID_TEST_TAB;
/
给出预期结果:
2 rows updated.
TEST_COMP_TRIGGER: BEFORE STATEMENT
TEST_COMP_TRIGGER: BEFORE EACH ROW
>>>> old: 1
>>>> new: 1
TEST_COMP_TRIGGER: BEFORE EACH ROW
>>>> old: 2
>>>> new: 2
TEST_COMP_TRIGGER: AFTER STATEMENT
但是当我添加AFTER EACH ROW声明时:
create or replace trigger TEST_COMP_TRIGGER
FOR UPDATE ON test_tab
COMPOUND TRIGGER
---- BEFORE
BEFORE STATEMENT
IS
BEGIN
dbms_output.put_line('TEST_COMP_TRIGGER: BEFORE STATEMENT');
NULL;
END BEFORE STATEMENT;
---- AFTER
AFTER STATEMENT IS
BEGIN
dbms_output.put_line('TEST_COMP_TRIGGER: AFTER STATEMENT');
NULL;
END AFTER STATEMENT;
---- BEFORE EACH
BEFORE EACH ROW IS
BEGIN
dbms_output.put_line('TEST_COMP_TRIGGER: BEFORE EACH ROW');
dbms_output.put_line('>>>> old: ' || :old.ID_TEST_TAB );
dbms_output.put_line('>>>> new: ' || :new.ID_TEST_TAB );
NULL;
END BEFORE EACH ROW;
---- AFTER EACH
AFTER EACH ROW
IS
BEGIN
dbms_output.put_line('TEST_COMP_TRIGGER: AFTER EACH ROW');
END AFTER EACH ROW;
END TEST_COMP_TRIGGER;
/
-----
SET serveroutput ON format wraped;
UPDATE test_tab SET test_tab.ID_TEST_TAB=test_tab.ID_TEST_TAB;
/
我还是空着:新:
2 rows updated.
TEST_COMP_TRIGGER: BEFORE STATEMENT
TEST_COMP_TRIGGER: BEFORE EACH ROW
>>>> old: 1
>>>> new:
TEST_COMP_TRIGGER: AFTER EACH ROW
TEST_COMP_TRIGGER: BEFORE EACH ROW
>>>> old: 2
>>>> new:
TEST_COMP_TRIGGER: AFTER EACH ROW
TEST_COMP_TRIGGER: AFTER STATEMENT
答案 0 :(得分:0)
时间点部分的顺序很重要,需要:
BEFORE STATEMENT
AFTER STATEMENT
BEFORE EACH ROW
AFTER EACH ROW
参考:Compound Trigger Sections, Oracle 11gR1 docs
以下脚本(在Oracle SQL Developer中运行,连接到Oracle Database 11g Express Edition Release 11.2.0.2.0 - Production
DROP TABLE test_tab;
CREATE TABLE test_tab ( ID_TEST_TAB NUMBER);
INSERT INTO test_tab VALUES (1);
INSERT INTO test_tab VALUES (2);
create or replace trigger TEST_COMP_TRIGGER
FOR UPDATE ON test_tab
COMPOUND TRIGGER
AFTER STATEMENT IS
BEGIN
dbms_output.put_line('TEST_COMP_TRIGGER: AFTER STATEMENT');
NULL;
END AFTER STATEMENT;
BEFORE EACH ROW IS
BEGIN
dbms_output.put_line('TEST_COMP_TRIGGER: BEFORE EACH ROW');
dbms_output.put_line('>>>> old: ' || :old.ID_TEST_TAB );
dbms_output.put_line('>>>> new: ' || :new.ID_TEST_TAB );
NULL;
END BEFORE EACH ROW;
END TEST_COMP_TRIGGER;
/
set serveroutput on format wraped;
UPDATE test_tab SET test_tab.ID_TEST_TAB=test_tab.ID_TEST_TAB+1;
/
产生输出:
table TEST_TAB dropped.
table TEST_TAB created.
1 rows inserted.
1 rows inserted.
TRIGGER TEST_COMP_TRIGGER compiled
2 rows updated.
TEST_COMP_TRIGGER: BEFORE EACH ROW
>>>> old: 1
>>>> new: 2
TEST_COMP_TRIGGER: BEFORE EACH ROW
>>>> old: 2
>>>> new: 3
TEST_COMP_TRIGGER: AFTER STATEMENT
将它们换成错误的顺序,输出结束为:
table TEST_TAB dropped.
table TEST_TAB created.
1 rows inserted.
1 rows inserted.
TRIGGER TEST_COMP_TRIGGER compiled
2 rows updated.
TEST_COMP_TRIGGER: BEFORE EACH ROW
>>>> old: 1
>>>> new:
TEST_COMP_TRIGGER: BEFORE EACH ROW
>>>> old: 2
>>>> new:
TEST_COMP_TRIGGER: AFTER STATEMENT
答案 1 :(得分:0)
以下脚本按预期工作。
DROP TABLE test_tab;
CREATE TABLE test_tab ( IDNO NUMBER);
INSERT INTO test_tab VALUES (1);
INSERT INTO test_tab VALUES (2);
create or replace trigger TEST_COMP_TRIGGER
FOR UPDATE ON test_tab
COMPOUND TRIGGER
---- BEFORE
BEFORE STATEMENT IS
BEGIN
dbms_output.put_line('TEST_COMP_TRIGGER: BEFORE STATEMENT');
END BEFORE STATEMENT;
---- AFTER
AFTER STATEMENT IS
BEGIN
dbms_output.put_line('TEST_COMP_TRIGGER: AFTER STATEMENT');
END AFTER STATEMENT;
---- BEFORE EACH
BEFORE EACH ROW IS
BEGIN
dbms_output.put('TEST_COMP_TRIGGER: BEFORE EACH ROW');
dbms_output.put(' old: ' || :old.IDNO || ' new: ' || :new.IDNO);
:New.IDNO := :new.IDNO + 1;
dbms_output.put_line(' old: ' || :old.IDNO || ' new: ' || :new.IDNO);
END BEFORE EACH ROW;
---- AFTER EACH
AFTER EACH ROW IS
BEGIN
dbms_output.put('TEST_COMP_TRIGGER: AFTER EACH ROW');
dbms_output.put_line(' old: ' || :old.IDNO || ' new: ' || :new.IDNO);
END AFTER EACH ROW;
END TEST_COMP_TRIGGER;
/
set serveroutput on format wraped;
UPDATE test_tab SET test_tab.IDNO=test_tab.IDNO+1;
/
生成输出:
table TEST_TAB dropped.
table TEST_TAB created.
1 rows inserted.
1 rows inserted.
TRIGGER TEST_COMP_TRIGGER compiled
2 rows updated.
TEST_COMP_TRIGGER: BEFORE STATEMENT
TEST_COMP_TRIGGER: BEFORE EACH ROW old: 1 new: 2 old: 1 new: 3
TEST_COMP_TRIGGER: AFTER EACH ROW old: 1 new: 3
TEST_COMP_TRIGGER: BEFORE EACH ROW old: 2 new: 3 old: 2 new: 4
TEST_COMP_TRIGGER: AFTER EACH ROW old: 2 new: 4
TEST_COMP_TRIGGER: AFTER STATEMENT
现在为了好玩。
非常挑剔和奇怪的行为。