【问题标题】:How can I get the inserted primary key value from AFTER INSERT trigger in Oracle?如何从 Oracle 中的 AFTER INSERT 触发器中获取插入的主键值?
【发布时间】:2019-01-22 22:55:46
【问题描述】:

我的 Oracle DB 有一个表 DOC_WF_COMM,它的主键是 DWFC_ID。主键值基于称为SQ_DOC_WF_COMM 的序列。

我在该表上创建了一个行级AFTER INSERT 触发器,在触发器内部我需要将插入的记录与其他一些表连接起来,如下所示:

create or replace TRIGGER TRG_DOC_WF_COMM_AFT_INS AFTER INSERT ON DOC_WF_COMM REFERENCING OLD AS OLD NEW AS NEW FOR EACH ROW
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
L_SUBJECT VARCHAR2(300);
L_BODY CLOB;

L_PNT_CODE VARCHAR(100) := NULL;
L_DR_PRJ_ID NUMBER(12);
L_STR_EMAIL VARCHAR2(120);
L_DWFC_TO_USR_ID VARCHAR2(12);

L_PNT_ID NUMBER(12);
L_PNT_EMAIL_YN VARCHAR(1);
L_PNT_ACTIVE_YN VARCHAR(1);
L_PNT_NOTIFY_YN VARCHAR(1);

BEGIN
    IF INSERTING THEN
        L_PNT_CODE := 'WFNT_MESSAGE';


        SELECT DR_PRJ_ID, STR_EMAIL, DWFC_TO_USR_ID INTO L_DR_PRJ_ID, L_STR_EMAIL, L_DWFC_TO_USR_ID
        FROM DOC_WF_COMM
        JOIN DOC_WF_USERS ON DWFU_ID = DWFC_DWFU_ID
        JOIN DOC_WORKFLOW ON DWF_ID = DWFU_DWF_ID
        JOIN DOCUMENT_REF ON DR_ID = DWF_DR_ID
        JOIN ST_REGISTER ON STR_ID = DWFU_STR_ID
        WHERE DWFC_ID = :NEW.DWFC_ID AND DWFC_RESPONSE IS NULL;

        -- SOME QUERIES HERE
    END IF;
END;

触发器编译成功,当我将记录插入DOC_WF_COMM 表时,我收到此错误:

ORA-01403: no data found ORA-06512

WHERE 子句中的错误是 :NEW.DWFC_ID,我已将其更改为以下值:

  • :OLD.DWFC_ID
  • SQ_DOC_WF_COMM.NEXTVAL
  • SQ_DOC_WF_COMM.CURRVAL

但没有任何运气。知道为什么会出现此错误以及如何解决吗?

【问题讨论】:

  • 这是什么触发器?行级别还是语句级别?
  • 它是一个行级触发器
  • 你能分享整个触发代码吗?我只需要了解你想要做什么。也请分享插入查询
  • 在插入 DOC_WF_COMM 后创建或替换 TRGGER TRG_DOC_WF_COMM_AFT_INS 将每行引用旧为新的为新的 声明 PRAGMA AUTONOMOUS_TRANSACTION; L_PNT_CODE VARCHAR(100) := 'WFNT_MESSAGE'; L_DR_PRJ_ID 编号(12); L_STR_EMAIL VARCHAR2(120); L_DWFC_TO_USR_ID VARCHAR2(12); BEGIN -- 上面给出的查询如果 L_DWFC_TO_USR_ID 不为 NULL 那么 --Some INSERT QUERIES END IF;万一;结束;
  • 请使用完整的触发代码更新您的问题 - 不要将其作为评论发布。另外,您确定相应的连接会总是返回结果吗? (即使DWFC_ID 是正确的)。

标签: oracle oracle11g oracle10g oracle-sqldeveloper database-trigger


【解决方案1】:

我将触发器内的查询更改为这个,它工作正常

SELECT STR_PRJ_ID, STR_EMAIL, :NEW.DWFC_TO_USR_ID INTO L_DR_PRJ_ID, L_STR_EMAIL, L_DWFC_TO_USR_ID
FROM DOC_WF_USERS, ST_REGISTER
WHERE :NEW.DWFC_TO_USR_ID = DWFU_US_ID AND DWFU_STR_ID = STR_ID AND DWFU_ID = :NEW.DWFC_DWFU_ID;

不知道为什么。如果有人能找出问题中给出的查询中的错误,请告诉我。谢谢

【讨论】:

    【解决方案2】:

    问题是触发器中的这一行:

    PRAGMA AUTONOMOUS_TRANSACTION;
    

    这意味着触发器在单独的会话中作为隔离事务执行,这意味着它无法看到任何其他会话的未提交状态。至关重要的是,这包括触发触发器的会话,因此自主事务无法看到您刚刚插入的记录。因此,NO_DATA_FOUND。

    您还没有发布整个触发器或解释您想要做什么,所以只有您知道为什么要包含 PRAGMA。但是,您可能不需要它。删除 PRAGMA(和 COMMIT),您的触发器应该可以正常工作。

    【讨论】:

      【解决方案3】:

      如果我理解正确,请创建一个局部变量并将下一个序列值放入其中。然后可以在整个代码中引用它,始终具有相同的值。像这样的:

      declare
        l_seq number := my_seq.nextval;
      begin
        insert into table_a (id, ...) values (l_seq, ...);
        update table_b set id = l_seq where ...
        select ... into ... from ... where id = l_seq;
      end;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-03-29
        • 2020-12-23
        • 2018-05-20
        • 1970-01-01
        • 2023-02-01
        • 1970-01-01
        • 2017-04-10
        • 1970-01-01
        相关资源
        最近更新 更多