在PL/SQL中创建触发抛出编译错误

Lis*_*a14 1 database oracle triggers plsql packages

我以用户ADMIN身份登录并执行PROCEDURE P1来检查和捕获日志.我在创建触发器时遇到错误

PROCEDURE P1
IS
BEGIN
INSERT statement
BEGIN
---
EXCEPTION

WHEN others THEN
  error_mgr.record_error();
 END P1;
Run Code Online (Sandbox Code Playgroud)

AS ADMIN用户没有足够的priveledge我作为另一个用户EXTRACT登录并创建了包error_mgr

create or replace
PACKAGE BODY error_mgr
IS
PROCEDURE record_error
 IS
 PRAGMA AUTONOMOUS_TRANSACTION;
 l_code  INTEGER := SQLCODE;
 l_mesg VARCHAR2(32767) := SQLERRM; 
 BEGIN
 INSERT INTO EXTRACT.error_log 
(created_on,created_by,errorcode,callstack,errorstack,backtrace,error_info) 
 VALUES(SYSDATE,USER,l_code,sys.DBMS_UTILITY.format_call_stack,null,
  sys.DBMS_UTILITY.format_error_backtrace,l_mesg);
        DBMS_OUTPUT.PUT_LINE('ERROR!!');  
COMMIT;
END record_error;
END error_mgr;
Run Code Online (Sandbox Code Playgroud)

注意:EXTRACT也是用户名和架构

提取模式中的ERROR LOG表有一个自动生成列id(LOG_ID)所以在EXTRACT模式中我使用的是序列和触发器

  SEQUENCE:
   CREATE SEQUENCE "EXTRACT"."SEQ_error_log" MINVALUE 1 MAXVALUE 
  9999999999999999999999999999 INCREMENT BY 1 START WITH 335 CACHE 20 NOORDER 
CYCLE ;
Run Code Online (Sandbox Code Playgroud)

触发:

 CREATE TRIGGER EXTRACT.BI_error_log
 BEFORE INSERT ON INO_EIR_EXTRACT.error_log
 REFERENCING NEW AS NEW OLD AS OLD
 FOR EACH ROW

 BEGIN
 -- Set column from sequence
 If (:NEW.LOG_ID IS NULL)
 THEN
  SELECT EXTRACT.SEQ_error_log.NEXTVAL INTO :NEW.LOG_ID FROM dual;
 END IF;
 END;
Run Code Online (Sandbox Code Playgroud)

错误:

PL/SQL:SQL语句忽略
PL/SQL:ORA2289序列不存在.

虽然我已经执行了序列,但我仍然遇到此错误.

Ale*_*ole 5

您已使用带引号的标识符创建序列:当您使用不带引号的引用时,SEQ_error_logOracle会在数据字典中查找全部为大写的名称,'SEQ_ERROR_LOG'.但是你创造了它

CREATE SEQUENCE "EXTRACT"."SEQ_error_log"
Run Code Online (Sandbox Code Playgroud)

这意味着它出现在完全一样的数据字典,没有什么配套uppsercase版本,每当你使用它,你必须使用带引号的标识符太,在完全相同的情况下,名称:

If (:NEW.LOG_ID IS NULL)
THEN
  SELECT EXTRACT."SEQ_error_log".NEXTVAL INTO :NEW.LOG_ID FROM dual;
END IF;
Run Code Online (Sandbox Code Playgroud)

或更简单地说:

If (:NEW.LOG_ID IS NULL)
THEN
  :NEW.LOG_ID := EXTRACT."SEQ_error_log".NEXTVAL;
END IF;
Run Code Online (Sandbox Code Playgroud)

这将是在长期内更好地重新创建序列,如果你还没有使用它的值填充任何表行或不知道如何调整它的初始值进行补偿,不具有带引号的标识符:

DROP SEQUENCE "EXTRACT"."SEQ_error_log";
CREATE SEQUENCE "EXTRACT"."SEQ_ERROR_LOG" START WITH 335;
Run Code Online (Sandbox Code Playgroud)

现在,显然我仍然在标识符周围加上双引号,但因为实际名称都是大写且合法的(请参阅开头的文档链接),这与说:

CREATE SEQUENCE extract.seq_error_log START WITH 335;
Run Code Online (Sandbox Code Playgroud)

而无论哪种方式的顺序可以被称为要么引用为你喜欢的任何情况下大写或不带引号的- ,extract.seq_error_log,EXTRACT.SEQ_ERROR_LOG,EXTRACT.SEQ_error_log,extract.SeQ_ErRoR_lOg或任何你喜欢的.您在现有触发器代码中的使用方式也将起作用.

就个人而言,我倾向于以小写的方式做所有事情 - 但我会建议你选择的任何你仍然使用它,因为编码风格使代码更容易阅读和维护.