【问题标题】:Oracle trigger is being called, but nothing happens正在调用 Oracle 触发器,但没有任何反应
【发布时间】: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


【解决方案1】:

找到解决方案:在我的过程中,缺少一个在目标表中设置为 NOT NULL 的列。 我做了什么:

  • 我将这个缺失的列添加到 INSERT 语句中
  • 然后我不得不 将insert into DEVLOGSAUTONOMOUS TRANSACTION 删除为 以及我在上面的 UPDATE 部分中插入的 COMMIT 语句。

但是,我不知道为什么我的异常处理程序在过程/触发器中没有捕获到非 NULL 约束违规。

预言机对我来说仍然不是很有预测性......

【讨论】:

    猜你喜欢
    • 2012-12-20
    • 1970-01-01
    • 2017-09-05
    • 1970-01-01
    • 1970-01-01
    • 2022-12-03
    • 1970-01-01
    • 1970-01-01
    • 2013-03-24
    相关资源
    最近更新 更多