[英]Sequence in Oracle/PostgreSQL with no ID in insert statement
我嘗試使用巧妙的序列生成器創建表以使用此插入結構:
insert into SOMEUSERS (SOMEUSERS_NAME, SOMEUSERS_PASSWORD)
values ('Artem', 'PracTimPatie');
代替這個:
insert into SOMEUSERS (SOMEUSERS_ID, SOMEUSERS_NAME, SOMEUSERS_PASSWORD)
values (2, 'Artem', 'PracTimPatie');
或此結構:
insert into SOMEUSERS (SOMEUSERS_ID, SOMEUSERS_NAME, SOMEUSERS_PASSWORD)
values (GEN_ID_SOMEUSERS.nextval, 'Artem', 'PracTimPatie');
當我執行以下sql腳本時:
create sequence gen_id_someUsers START WITH 1 INCREMENT BY 1 NOCACHE NOCYCLE;
CREATE TABLE loc_db.someUsers
( someUsers_id number(10) DEFAULT gen_id_someUsers.NEXTVAL NOT NULL, --because of this row
someUsers_name varchar2(50) NOT NULL,
someUsers_password varchar2(50),
CONSTRAINT someUsers_pk PRIMARY KEY (someUsers_id)
);
發出以下通知:
錯誤報告-SQL錯誤:ORA-00984:此處不允許在該列00984。00000-“此處不允許在該列”
為了清楚起見,在這種情況下表示:
...
CREATE TABLE loc_db.someUsers
( someUsers_id number(10) NOT NULL, --correct this row
...
已創建序列GEN_ID_SOMEUSERS。
表LOC_DB.SOMEUSERS已創建。
(對於PostgreSQL也是如此 。如果沒有觸發器,則盡可能輕松)
在postgres中,只需使用如下序列:
CREATE TABLE SOMEUSERS (
SOMEUSERS_ID serial NOT NULL,
SOMEUSERS_NAME text,
SOMEUSERS_PASSWORD text
);
這樣,您的插入語句就很容易了:
INSERT INTO SOMEUSERS (SOMEUSERS_NAME, SOMEUSERS_PASSWORD)
values ('Artem', 'PracTimPatie');
如果您想查詢序列,則可以像查詢其他任何關系一樣查詢它。
Oracle 12c引入了標識列 :
CREATE TABLE SOMEUSERS (
SOMEUSERS_ID NUMBER(10) GENERATED ALWAYS AS IDENTITY
CONSTRAINT SOMEUSERS__SOMEUSERS_ID__PK PRIMARY KEY,
SOMEUSERS_NAME VARCHAR2(50)
CONSTRAINT SOMEUSERS__SOMEUSERS_NAME__NN NOT NULL,
SOMEUSERS_PASSWORD VARCHAR2(50)
);
如果要在早期版本中執行此操作,則需要一個觸發器和一個序列:
CREATE TABLE SOMEUSERS (
SOMEUSERS_ID NUMBER(10)
CONSTRAINT SOMEUSERS__SOMEUSERS_ID__PK PRIMARY KEY,
SOMEUSERS_NAME VARCHAR2(50)
CONSTRAINT SOMEUSERS__SOMEUSERS_NAME__NN NOT NULL,
SOMEUSERS_PASSWORD VARCHAR2(50)
);
/
CREATE SEQUENCE gen_id_someUsers START WITH 1 INCREMENT BY 1 NOCACHE NOCYCLE;
/
CREATE OR REPLACE TRIGGER SOMEUSERS__ID__TRG
BEFORE INSERT ON SOMEUSERS
FOR EACH ROW
BEGIN
:new.SOMEUSERS_ID := gen_id_someUsers.NEXTVAL;
END;
/
然后,您可以執行此操作(將Identity列或觸發器與您的序列結合使用):
INSERT INTO SOMEUSERS (
SOMEUSERS_NAME,
SOMEUSERS_PASSWORD
) VALUES (
'Name',
'Password'
);
其他答案已經解決了postgreSQL和Oracle 12c,因此在這里我將介紹Oracle 11.2或更早版本。
從《 11.1 SQL參考手冊》中:
默認
如果后續的INSERT語句省略了該列的值,則DEFAULT子句允許您指定要分配給該列的值。 表達式的數據類型必須與列的數據類型匹配。 該列還必須足夠長才能容納此表達式。
DEFAULT表達式可以包含任何SQL函數,只要該函數不返回文字參數,列引用或嵌套函數調用即可。
對默認列值的限制
DEFAULT表達式不能包含對 PL / SQL函數或其他列,偽列CURRVAL, NEXTVAL ,LEVEL,PRIOR和ROWNUM的引用 ,或未完全指定的日期常量。
(強調我的)
因此,由於您不能將sequence.NEXTVAL
作為DEFAULT值放入,因此基本上必須使用觸發器:
CREATE OR REPLACE TRIGGER SOMEUSERS_BI
BEFORE INSERT
ON LOC_DB.SOMEUSERS
FOR EACH ROW
BEGIN
IF :NEW.SOMEUSERS_ID THEN
:NEW.SOMEUSERS_ID := GEN_ID_SOMEUSERS.NEXTVAL;
END IF;
END SOMEUSERS_BI;
根據我的經驗,沒有比使用觸發器(如Oracle 11.2或更早版本)更可靠的選擇。
祝你好運。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.