Sequence in Oracle/PostgreSQL with no ID in insert statement

梦想的初衷 提交于 2019-12-12 02:32:07

问题


I'm try to create table with clever sequence generator for using this insert-strucure:

insert into SOMEUSERS (SOMEUSERS_NAME, SOMEUSERS_PASSWORD) 
values ('Artem', 'PracTimPatie');

instead of this:

insert into SOMEUSERS (SOMEUSERS_ID, SOMEUSERS_NAME, SOMEUSERS_PASSWORD) 
values (2, 'Artem', 'PracTimPatie');

or this structure:

insert into SOMEUSERS (SOMEUSERS_ID, SOMEUSERS_NAME, SOMEUSERS_PASSWORD) 
values (GEN_ID_SOMEUSERS.nextval, 'Artem', 'PracTimPatie');

When I executing the following sql script:

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)
);

the following notice is given to me:

Error report - SQL Error: ORA-00984: column not allowed here 00984. 00000 - "column not allowed here"

For clarity, said that in this case:

    ...
CREATE TABLE loc_db.someUsers
( someUsers_id number(10) NOT NULL, --correct this row
...

Sequence GEN_ID_SOMEUSERS created.

Table LOC_DB.SOMEUSERS created.

How can I configure comfortable sequence generator?

(in case of PostgreSQL too. If possible with no trigger(as easily as possible)


回答1:


Oracle 12c introduces Identity columns:

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)
);

If you want to do it in earlier versions then you will need a trigger and a sequence:

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;
/

You can then just do (either with the identity column or the trigger combined with your sequence):

INSERT INTO SOMEUSERS (
  SOMEUSERS_NAME,
  SOMEUSERS_PASSWORD
) VALUES (
  'Name',
  'Password'
);



回答2:


In postgres just use a serial like this:

CREATE TABLE SOMEUSERS (
  SOMEUSERS_ID serial NOT NULL,
  SOMEUSERS_NAME text,
  SOMEUSERS_PASSWORD text
);

Your insert statement is then easy as:

INSERT INTO SOMEUSERS (SOMEUSERS_NAME, SOMEUSERS_PASSWORD) 
values ('Artem', 'PracTimPatie');

If you wanna query the sequence you can just query it like any other relation.




回答3:


Other answers have addressed postgreSQL and Oracle 12c, so I'll address Oracle 11.2 or earlier here.

From the 11.1 SQL Reference Manual:

DEFAULT

The DEFAULT clause lets you specify a value to be assigned to the column if a subsequent INSERT statement omits a value for the column. The datatype of the expression must match the datatype of the column. The column must also be long enough to hold this expression.

The DEFAULT expression can include any SQL function as long as the function does not return a literal argument, a column reference, or a nested function invocation.

Restriction on Default Column Values

A DEFAULT expression cannot contain references to PL/SQL functions or to other columns, the pseudocolumns CURRVAL, NEXTVAL, LEVEL, PRIOR, and ROWNUM, or date constants that are not fully specified.

(Emphasis mine)

So since you can't put sequence.NEXTVAL in as a DEFAULT value you're basically going to have to use a trigger:

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;

In my experience there is no reliable alternative to using a trigger such as this in Oracle 11.2 or earlier.

Best of luck.



来源:https://stackoverflow.com/questions/31546058/sequence-in-oracle-postgresql-with-no-id-in-insert-statement

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!