我已经创建了一个数据库,我想在其中自动递增主键。我试图触发它,但出现了上述错误这是我对表格的描述:
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_ID
是NUMBER
,那么触发代码就过于复杂了,因为无论你对这些函数做什么,最终都只得到一个数字。正如您从我的示例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年代的一个坏习惯。