Oracle 10g Error: Warning: Trigger created with compilation errors

Oracle 10g Error: Warning: Trigger created with compilation errors

我已经创建了数据库,我想在其中自动增加主键。我试图触发它但出现上述错误 这是我对 table:

的描述
SQL> desc users
Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 USER_ID                                   NOT NULL NUMBER(8)
 FIRST_NAME                                NOT NULL VARCHAR2(50)
 LAST_NAME                                 NOT NULL VARCHAR2(50)
 CITY                                               VARCHAR2(20)
 COUNTRY                                            VARCHAR2(20)
 PASSWORD                                  NOT NULL VARCHAR2(16)
 EMAIL_ID                                  NOT NULL VARCHAR2(50)

当我尝试触发它时出现错误:

 CREATE SEQUENCE SYSTEM.MYSEQ
 2  START WITH 1
 3  MAXVALUE 99999999
 4  MINVALUE 1
 5  NOCYCLE
 6  CACHE 20
 7  NOORDER;

CREATE OR REPLACE TRIGGER TR_USERS BEFORE INSERT ON USERS FOR EACH ROW
2  BEGIN SELECT LPAD(LTRIM(RTRIM(TO_CHAR(MYSEQ.NEXTVAL))),10,'0') INTO :NEW.USER_ID FROM DUAL;
3  /

请帮我解决这个错误。

编译 而言,触发器没有任何问题(除了您“忘记”END 的事实)。

SQL> CREATE OR REPLACE TRIGGER TR_USERS
  2    BEFORE INSERT ON USERS
  3    FOR EACH ROW
  4  BEGIN
  5    SELECT lpad(ltrim(rtrim(to_char(myseq.nextval))), 10, '0')
  6    INTO :new.user_id
  7    FROM dual;
  8  END;
  9  /

Trigger created.

SQL> INSERT INTO USERS (FIRST_NAME) VALUES ('Little');

1 row created.

SQL> SELECT * FROM users;

   USER_ID FIRST_NAME      LAST_NAE   CITY       COUNTRY    PASSW EMAIL_ID
---------- --------------- ---------- ---------- ---------- ----- --------------------
         1 Little

SQL>

但是,如果 USER_IDNUMBER,那么您的触发器代码就过于复杂了,因为无论您使用这些函数做什么,最终都会得到一个 。从我的示例中可以看出,USER_ID = 1.

如果是VARCHAR2,那么

SQL> TRUNCATE TABLE users;

Table truncated.

SQL> ALTER TABLE USERS MODIFY user_id VARCHAR2(10);

Table altered.

SQL> INSERT INTO USERS (FIRST_NAME) VALUES ('Foot');

1 row created.

SQL> SELECT * FROM users;

USER_ID    FIRST_NAME      LAST_NAE   CITY       COUNTRY    PASSW EMAIL_ID
---------- --------------- ---------- ---------- ---------- ----- --------------------
0000000002 Foot

SQL>

看出区别了吗?


触发器本来可以更简单(但不是 更简单;毕竟你在 10g 上)因为没有什么可以 trim :

SQL> CREATE OR REPLACE TRIGGER TR_USERS
  2    BEFORE INSERT ON USERS
  3    FOR EACH ROW
  4  BEGIN
  5    SELECT lpad(to_char(myseq.nextval), 10, '0')
  6    INTO :new.user_id
  7    FROM dual;
  8  END;
  9  /

Trigger created.

SQL> INSERT INTO USERS (FIRST_NAME) VALUES ('Krishna');

1 row created.

SQL> SELECT * FROM users;

USER_ID    FIRST_NAME      LAST_NAE   CITY       COUNTRY    PASSW EMAIL_ID
---------- --------------- ---------- ---------- ---------- ----- --------------------
0000000002 Foot
0000000003 Krishna

SQL>

您遇到错误,因为您缺少触发器的 END:

CREATE OR REPLACE TRIGGER TR_USERS
  BEFORE INSERT ON USERS
  FOR EACH ROW
BEGIN
  SELECT LPAD(LTRIM(RTRIM(TO_CHAR(MYSEQ.NEXTVAL))),10,'0')
    INTO :NEW.USER_ID 
  FROM DUAL;
END; -- <=== this one
/

顺便说一句,触发器似乎没有多大意义。 LPAD(LTRIM(RTRIM(TO_CHAR(MYSEQ.NEXTVAL))),10,'0') 只是一个混淆的 TO_CHAR(MYSEQ.NEXTVAL, 'FM0000000000'),但是,当 USERS.USER_ID 是数字时,为什么要创建一个带有前导零的字符串???你把 123 变成 '0000000123' 只是为了将它存储为 123.

除了缺少 end 关键字外,您不需要所有字符格式或 'select from dual'。我只会使用:

create or replace trigger tr_users
    before insert on users
    for each row
begin
    :new.user_id := myseq.nextval; 
end;

顺便说一句,你的序列也可以更简单地写成:

create sequence myseq;

还有,不用大写编码。这是 70 年代以来的坏习惯。