【问题标题】:Compilation errors with 12c Trigger statements?12c 触发器语句的编译错误?
【发布时间】:2014-05-27 19:32:43
【问题描述】:

第一个帖子,这是一个大问题。我已经坚持了一段时间,并且它阻碍了我的项目的其余部分 - 自从我在数据库开发方面做了很多事情以来已经很长时间了。我上次使用 Oracle 是在 11g 上,但我试图从旧项目中重用的语法现在似乎不起作用,我只能摸不着头脑。如果有人能指出我遗漏的(可能)显而易见的事情,我会非常感激不尽?

不确定我是否在这里发布了太多内容,如果有,请说出来。


这是表 CREATE 和 TRIGGER 语句

 1. CREATE
 2.   TABLE employees
 3.     (
 4.       Employee_id       NUMBER   (4)   NOT NULL ,
 5.       firstname         VARCHAR2 (64)  NOT NULL ,
 6.       surname           VARCHAR2 (64)  NOT NULL ,
 7.       email             VARCHAR2 (256) NOT NULL ,
 8.       telephone         VARCHAR2 (20) ,
 9.       emp_password      VARCHAR2 (32)  NOT NULL ,
 10.      startdate         DATE           NOT NULL ,
 11.      organisation_id   NUMBER   (3)   NOT NULL ,
 12.      department_id     NUMBER   (2)   NOT NULL ,
 13.      jobtitle_id       NUMBER   (3)   NOT NULL ,
 14.      user_level        NUMBER   (1)   NOT NULL ,
 15.       Emp_added_by      NUMBER   (4)   NOT NULL ,   
 16.       Emp_added_on      TIMESTAMP      NOT NULL ,
 17.       Emp_updated_by    NUMBER   (4)   NOT NULL ,
 18.       Emp_updated_on    TIMESTAMP      NOT NULL
 19.     ) ;

 20.   ALTER TABLE employees ADD CONSTRAINT employees_PK 
 21.     PRIMARY KEY ( employee_id ) ;

以及序列和语句;

22. CREATE SEQUENCE "seq_employee_id" MINVALUE 1 MAXVALUE 9999 INCREMENT BY 1 
23. START WITH 1 NOCACHE ORDER NOCYCLE ;

最后是让我大吃一惊的触发器;

24. create or replace 
25. trigger trg_employees 
26. BEFORE 
27.  INSERT OR 
28.  UPDATE OF employee_id 
29.  ON employees FOR EACH ROW 
30. BEGIN 
31.   IF INSERTING THEN IF 
32.    :NEW.employee_id = NULL THEN
33.      SELECT seq_employee_id.NEXTVAL
34.      INTO :NEW.employee_id
35.      FROM sys.dual;
36.    END IF;
37.  END IF;
38.  /*format firstname to have initial capital letter*/
39.  :NEW.firstname := INITCAP(:NEW.firstname);
40.  /*format surname to have initial capital letter*/
41.  :NEW.surname := INITCAP(:NEW.surname);
42.  /*replace any characters other than digits with an empty string*/
43.  :NEW.telephone := REGEXP_REPLACE(:NEW.telephone, '[^[:digit:]]', '');
44.  /*adjust to (99999) 999999 format */
45.  :NEW.telephone := REGEXP_REPLACE(:NEW.telephone,
46.            '([[:digit:]]{5})([[:digit:]](6)', '(\1) \2');
47. END;

48. ELSIF UPDATING THEN
49.   SELECT SYSDATE INTO :NEW.employee_updated_on FROM sys.dual;
50. END IF;
51. END;

/*This trigger automatically inserts a timestamp into updated rows to show audit
details.*/
52. CREATE OR REPLACE TRIGGER trg_employee_update 
53. BEFORE UPDATE ON employees FOR EACH ROW 
54. BEGIN
  /* Update "employee_updated_on" to current system date*/
55.  :NEW.employee_updated_on := sysdate;
56. END;

我可以轻松创建表、约束和序列;但是当我运行触发器语句时,它会编译并出现以下错误

4,7 PL/SQL:忽略 SQL 语句 4,14 PL/SQL: ORA-02289: 序列不存在

现在显然序列 确实 存在,但我完全不知道为什么它无法识别它,因为我可以在我的数据库中很好地查看序列。我不知道我在第 10 行是否有语法错误,SELECT seq_employee_id.NEXTVAL,也许?

【问题讨论】:

  • 中间(ELSIF之前)的END;在做什么?
  • 我现在添加了行号,以便在故障排除方面有所帮助。你是说第47行吗?我想这就是触发器的插入部分的结尾?

标签: sql oracle triggers oracle12c


【解决方案1】:

您在触发器中引用的序列不存在。

如果您在 CREATE SEQUENCE 语句中的标识符周围使用双引号

CREATE SEQUENCE "seq_employee_id" MINVALUE 1 MAXVALUE 9999 INCREMENT BY 1 
START WITH 1 NOCACHE ORDER NOCYCLE ;

那么您正在创建一个区分大小写的标识符。如果这样做,则每次引用标识符时都需要使用双引号和正确的大小写来引用标识符。这通常很烦人,这就是为什么我从不建议创建区分大小写的标识符的原因。

SELECT "seq_employee_id".NEXTVAL
  INTO :NEW.employee_id
  FROM sys.dual;

从11g开始,可以通过对序列进行直接赋值来简化语句

:new.employee_id := "seq_employee_id".nextval;

实际上,我建议重新创建不带双引号的序列并使用直接分配给:new.employee_id

【讨论】:

  • 该死,我什至没有考虑那里的报价!我会试一试,看看会发生什么。为什么序列在我的数据库中是可见的?运行那个确切的语句后我可以看到它吗?
  • @nightwing_87 - 我不确定“在我的数据库中可见”是什么意思,或者您运行什么“确切语句”来“查看”序列。
  • 抱歉,我不知道正确的术语是什么——当我连接到我的 Oracle 服务器时,我可以通过 SQL 开发人员中的资源管理器/浏览器窗口从字面上看到我的架构中列出的序列。这有助于澄清我的意思吗?我刚刚运行了不带引号的序列,然后再次尝试触发。为了简单起见,我删除了第 38-46 行,到目前为止它似乎已经成功了,谢谢!我确实收到了第 38-46 行的 REGEXP 错误,但我会继续尝试。
  • @nightwing_87 - 您会在 GUI 中看到一个序列,该序列具有区分大小写的小写标识符。如果您使用双引号标识符运行 create sequence 语句,则该序列存在。它恰好与您的代码引用的标识符不同。
  • 啊好吧,这确实有道理!想我现在到了某个地方,插入部分的触发器运行良好,但我现在正在调整更新部分以正确获取 sysdate。感谢您的帮助:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-01-04
  • 1970-01-01
  • 1970-01-01
  • 2013-05-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多