Oracle 10g错误:警告:创建触发器时出现编译错误



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

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:

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它这一事实之外(。

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(,因为没有什么可以修剪

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关键字外,您不需要所有字符格式或"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;

此外,不需要用大写字母进行编码。这是20世纪70年代的一个坏习惯。

相关内容

最新更新