【发布时间】:2016-06-29 05:30:59
【问题描述】:
我有一个AFTER INSERT TRIGGER,它又调用了一个过程。触发器和过程正在正确地记录到表 DEVLOGS,似乎没有发生异常。
我的触发器:
CREATE OR REPLACE TRIGGER MYSCHEMA.MYTRIGGER
AFTER INSERT ON MYSCHEMA.MYTABLE
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
DECLARE err_msg varchar(1000);
BEGIN
-- Log start trigger
INSERT INTO DEVLOGS (TIMESTAMP, MSG ) values ( CURRENT_TIMESTAMP, 'Now starting TRIGGER MYTRIGGER' );
-- CALL Procedure:
MYSCHEMA.MYPROC(
:NEW.MNPDID,
NVL(:NEW.CTCAETERM,'NULL'),
NVL(:NEW.SO_NARRATIVE || :NEW.SO_NARRATIVE1 || :NEW.SO_NARRATIVE2,'NULL'),
NVL(:NEW.SO_TRUE,1),
NVL(:NEW.ADDINFO,'NULL'),
NVL(:NEW.SO_REL1,0),
NVL(:NEW.SO_REL2,0),
NVL(:NEW.SO_SOC1,'NULL')
);
-- Log end trigger
INSERT INTO DEVLOGS (TIMESTAMP, MNPDID, MSG ) values ( CURRENT_TIMESTAMP, :NEW.MNPDID, 'OK TRIGGER MYTRIGGER(' ||
:NEW.MNPDID || ', ' ||
NVL(:NEW.CTCAETERM,'NULL') || ', ' ||
NVL(:NEW.SO_NARRATIVE || :NEW.SO_NARRATIVE1 || :NEW.SO_NARRATIVE2,'NULL') || ', ' ||
NVL(:NEW.SO_TRUE,1) || ', ' ||
NVL(:NEW.ADDINFO,'NULL') || ', ' ||
NVL(:NEW.SO_REL1,0) || ', ' ||
NVL(:NEW.SO_REL2,0) || ', ' ||
NVL(:NEW.SO_SOC1,'NULL') || '). Terminated, no exception' );
EXCEPTION
WHEN OTHERS THEN
err_msg := SUBSTR(SQLERRM, 1, 1000);
INSERT INTO DEVLOGS (TIMESTAMP, MSG ) values ( CURRENT_TIMESTAMP, 'ERROR IN TRIGGER MYTRIGGER:' || err_msg );
END;
/
我的程序
CREATE OR REPLACE PACKAGE BODY MYSCHEMA.MYPACKAGE AS
PROCEDURE MYPROC(
ID DEVSAES.MNPDID%TYPE,
CTCAETERM DEVSAES.CTCAETERM%TYPE ,
SO_NARRATIVE DEVSAES.SO_NARRATIVE%TYPE,
SO_TRUE DEVSAES.TRUESAE%TYPE,
ADDINFO DEVSAES.ADDINFO%TYPE,
SO_REL1 DEVSAES.SO_REL1%TYPE,
SO_REL2 DEVSAES.SO_REL2%TYPE,
SO_SOC1 DEVSAES.SO_SOC1%TYPE)
IS
err_msg varchar2(1000);
BEGIN
INSERT INTO DEVLOGS (TIMESTAMP, MSG ) values ( current_timestamp, 'In PROCEDURE MYPROC: Now calling procedure with params: ' || ID || ', ' || CTCAETERM || ', ' || SO_NARRATIVE || ', ' || SO_TRUE || ', ' || ADDINFO || ', ' || SO_REL1 || ', ' || SO_REL2 || ', ' || SO_SOC1 );
INSERT INTO DEVSAES
SELECT
CN.PID
,AE.AEDATE
,AE.AEID
,ID
...
FROM TABLE1 CN
INNER JOIN TABLE2 AE
ON CN.CNID = AE.CNID
...
WHERE AE.MNPDID = ID;
INSERT INTO DEVLOGS (TIMESTAMP, MSG ) values ( current_timestamp, 'In PROCEDURE MYPROC: Procedure terminated.');
EXCEPTION
WHEN OTHERS THEN
err_msg := SUBSTR(SQLERRM, 1, 1000);
INSERT INTO DEVLOGS (TIMESTAMP, MSG ) values ( current_timestamp, 'In PROCEDURE MYPROC:' || err_msg );
END;
END MYPACKAGE;
/
现在查看日志时,没有引发异常:
14/03/2016 08:15:45.367522 Now startting TRIGGER MYTRIGGER
14/03/2016 08:15:45.673051 In PROCEDURE MYPROC: Now calling procedure with params: 998, Cataract, NULL, 1, NULL, 2, 4, Eye disorders
14/03/2016 08:15:46.910680 In PROCEDURE MYPROC: Procedure terminated.
14/03/2016 08:15:46.915188 998 OK TRIGGER MYTRIGGER(998, Cataract, NULL, 1, NULL, 2, 4, Eye disorders). Terminated, no exception
未在表 DEVSAES 中找到该过程实际应该写入的数据,此外,当我“手动”调用该过程(即之前没有触发器)时,然后值已正确插入!
更新
我现在已将程序加入到触发器中。进一步改进:
-
PRAGMA AUTONOMOUS TRANSACTION已添加 -
COMMIT最后添加 - 将
SQL%Rowcount记录到开发日志中。确实是0 rows inserted。
当我调用查询的 SELECT 部分并将 :NEW 变量替换为固定值(以模拟插入的参数)时,它返回一行,正是我喜欢自动插入到 DEVSAES 表中的那一行。
我修改后的查询如下:
CREATE OR REPLACE TRIGGER MYSCHEMA.MYTRIGGER
AFTER INSERT
ON MYSCHEMA.MYTABLE
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
DECLARE
err_msg varchar(1000);
v_count integer;
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
INSERT INTO DEVLOGS (TIMESTAMP, MSG) values ( current_timestamp,
'In Trigger MYTRIGGER: Now calling INSERT with params: ' || :NEW.MNPDID || ', ' || :NEW.CTCAETERM );
INSERT INTO DEVSAES
SELECT
CN.PID
,AE.AEDATE
,AE.AEID
,:NEW.ID
,:NEW.CTCAETERM
...
FROM MYSCHEMA.CASENODE CN
INNER JOIN MYSCHEMA.ADVERSEEVENT AE
ON CN.CNID = AE.CNID
...
WHERE D2.MNPDID = :NEW.MNPDID;
v_count := SQL%ROWCOUNT;
INSERT INTO DEVLOGS (TIMESTAMP, MSG ) VALUES ( CURRENT_TIMESTAMP, 'Trigger MYSCHEMA.MYTRIGGER terminated. No exceptions catched. ' || v_count ||' rows inserted. Now comitting.');
COMMIT;
EXCEPTION
WHEN OTHERS THEN
err_msg := SUBSTR(SQLERRM, 1, 1000);
INSERT INTO DEVLOGS (TIMESTAMP, MSG ) VALUES ( CURRENT_TIMESTAMP, 'ERROR IN TRIGGER MYTRIGGER:' || err_msg );
END;
/
日志:
17/03/2016 14:05:51.664756 Trigger MYSCHEMA.MYTRIGGER terminated. No exceptions catched. 0 rows inserted. Now comitting.
17/03/2016 14:05:51.664153 In TRIGGER MYTRIGGER: Now calling INSERT with params: 1056, Cushingoid, , , , 2, 3, Endocrine disorders
【问题讨论】:
-
尝试使用
SQL%ROWCOUNT来检查您从 select 到 DEVSAES 的插入是否有效 -
你
COMMIT过程/触发器中的插入了吗? -
为什么要使用触发器?创建一个过程来封装触发器的所有逻辑和它触发的插入,然后调用该过程而不是使用插入。
-
你的问题在这里:WHERE D2.MNPDID = ID;您的表可能有一个名为 ID 的列,因此未使用过程参数。
-
日志记录程序也应该使用 PRAGMA AUTONOMOUS TRANSACTION,这样无论任何操作或其他故障如何,都会发生日志记录。你的呢?
标签: oracle stored-procedures oracle11g exception-handling triggers