在PL / SQL中创建触发器引发编译错误

时间:2018-07-10 14:57:30

标签: database oracle plsql triggers packages

我以用户ADMIN的身份登录,并执行PROCEDURE P1来检查和捕获日志。创建触发器时出现错误

PROCEDURE P1
IS
BEGIN
INSERT statement
BEGIN
---
EXCEPTION

WHEN others THEN
  error_mgr.record_error();
 END P1;

AS ADMIN用户没有足够的权限,我以另一个用户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;

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

提取模式中的错误日志表具有自动生成列  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 ;

触发:

 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;

错误:

  

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

尽管我已经执行了序列,但仍然出现此错误。

1 个答案:

答案 0 :(得分:5)

您已经创建了序列with a quoted identifier:使用SEQ_error_log之类的无引号的引用时,Oracle在数据字典中查找全为大写的名称'SEQ_ERROR_LOG'。但是您将其创建为

CREATE SEQUENCE "EXTRACT"."SEQ_error_log"

这意味着它在数据字典中的显示完全一样,没有匹配的大写版本,并且每当使用它时,也必须使用带引号的标识符,名称的大小写完全相同:

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

或更简单地说:

If (:NEW.LOG_ID IS NULL)
THEN
  :NEW.LOG_ID := EXTRACT."SEQ_error_log".NEXTVAL;
END IF;

从长远来看,如果您还没有使用其值填充任何表行或者不知道如何调整其起始值以进行补偿(不带引号的标识符),那么重新创建序列会更好: / p>

DROP SEQUENCE "EXTRACT"."SEQ_error_log";
CREATE SEQUENCE "EXTRACT"."SEQ_ERROR_LOG" START WITH 335;

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

CREATE SEQUENCE extract.seq_error_log START WITH 335;

,并且在您喜欢的任何情况下-extract.seq_error_logEXTRACT.SEQ_ERROR_LOGEXTRACT.SEQ_error_logextract.SeQ_ErRoR_lOg或其他任何方式都可以将序列引用为大写或不引用你比较喜欢。在现有触发代码中使用它的方式也将起作用。

我个人倾向于使用小写形式进行所有操作-但我建议您选择使用任何内容,但仍应始终使用它,因为编码风格使代码更易于阅读和维护。