0

第一篇文章,这是一个大问题。我已经坚持了一段时间,它阻碍了我的项目的其余部分 - 自从我在数据库开发方面做了很多事情以来已经很长时间了。我上次使用 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,也许?

4

1 回答 1

0

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

如果您在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.

于 2014-04-14T01:15:50.410 回答