如何在Oracle上使用AUTO_INCREMENT创buildid?

在Oracle中,似乎没有AUTO_INCREMENT的概念,直到并包括11g版本。

如何创build一个在Oracle 11g中像自动增量一样的列?

从Oracle 11g开始,在Oracle中不存在“auto_increment”或“identity”列。 但是,您可以使用序列和触发器轻松进行build模:

表格定义:

 CREATE TABLE departments ( ID NUMBER(10) NOT NULL, DESCRIPTION VARCHAR2(50) NOT NULL); ALTER TABLE departments ADD ( CONSTRAINT dept_pk PRIMARY KEY (ID)); CREATE SEQUENCE dept_seq START WITH 1; 

触发器定义:

 CREATE OR REPLACE TRIGGER dept_bir BEFORE INSERT ON departments FOR EACH ROW BEGIN SELECT dept_seq.NEXTVAL INTO :new.id FROM dual; END; / 

更新:

IDENTITY列现已在Oracle 12c上提供:

 create table t1 ( c1 NUMBER GENERATED by default on null as IDENTITY, c2 VARCHAR2(10) ); 

或者指定起始值和增量值,还可以防止对标识列进行任何插入( GENERATED ALWAYS )(仅限于Oracle 12c +)

 create table t1 ( c1 NUMBER GENERATED ALWAYS as IDENTITY(START with 1 INCREMENT by 1), c2 VARCHAR2(10) ); 

SYS_GUID返回一个GUID–一个全局唯一的ID。 SYS_GUIDRAW(16) 。 它不会生成递增的数字值。

如果你想创build一个递增的数字键,你需要创build一个序列。

 CREATE SEQUENCE name_of_sequence START WITH 1 INCREMENT BY 1 CACHE 100; 

然后,您可以在INSERT语句中使用该序列

 INSERT INTO name_of_table( primary_key_column, <<other columns>> ) VALUES( name_of_sequence.nextval, <<other values>> ); 

或者你可以定义一个触发器,使用序列自动填充主键值

 CREATE OR REPLACE TRIGGER trigger_name BEFORE INSERT ON table_name FOR EACH ROW BEGIN SELECT name_of_sequence.nextval INTO :new.primary_key_column FROM dual; END; 

如果您正在使用Oracle 11.1或更高版本,则可以简化一下触发器

 CREATE OR REPLACE TRIGGER trigger_name BEFORE INSERT ON table_name FOR EACH ROW BEGIN :new.primary_key_column := name_of_sequence.nextval; END; 

如果你真的想使用SYS_GUID

 CREATE TABLE table_name ( primary_key_column raw(16) default sys_guid() primary key, <<other columns>> ) 

在Oracle 12c以后,你可以做类似的事情,

 CREATE TABLE MAPS ( MAP_ID INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1), MAP_NAME VARCHAR(24) NOT NULL, UNIQUE (MAP_ID, MAP_NAME) ) 

而在Oracle(Pre 12c)中。

 -- create table CREATE TABLE MAPS ( MAP_ID INTEGER NOT NULL , MAP_NAME VARCHAR(24) NOT NULL, UNIQUE (MAP_ID, MAP_NAME) ) --create sequence CREATE SEQUENCE MAPS_SEQ; -- create tigger using the sequence CREATE OR REPLACE TRIGGER MAPS_TRG BEFORE INSERT ON MAPS FOR EACH ROW WHEN (new.MAP_ID IS NULL) BEGIN SELECT MAP_ID_SEQ.NEXTVAL INTO :new.MAP_ID FROM dual; END; / --enable the trigger ALTER TRIGGER MAPS_TRG ENABLE ; 

这里有三种口味:

  1. 数字 。 简单增加的数值,例如1,2,3,….
  2. GUID 。 全局唯一标识符,作为RAW数据types。
  3. GUID(string) 。 和上面一样,但作为一个string,可能更容易处理一些语言。

x是标识列。 在每个例子中用你的表名replaceFOO

 -- numerical identity, eg 1,2,3... create table FOO ( x number primary key ); create sequence FOO_seq; create or replace trigger FOO_trg before insert on FOO for each row begin select FOO_seq.nextval into :new.x from dual; end; / -- GUID identity, eg 7CFF0C304187716EE040488AA1F9749A -- use the commented out lines if you prefer RAW over VARCHAR2. create table FOO ( x varchar(32) primary key -- string version -- x raw(32) primary key -- raw version ); create or replace trigger FOO_trg before insert on FOO for each row begin select cast(sys_guid() as varchar2(32)) into :new.x from dual; -- string version -- select sys_guid() into :new.x from dual; -- raw version end; / 

更新:

Oracle 12c引入了这两个不依赖于触发器的变体:

 create table mytable(id number default mysequence.nextval); create table mytable(id number generated as identity); 

第一个以传统方式使用序列; 第二个在内部pipe理价值。

假设你的意思是像SQL Server标识列一样的列?

在Oracle中,您使用SEQUENCE来实现相同的function。 我会看看我能不能find一个好的链接,并在这里发布。

更新:看起来像你自己find它。 无论如何,这里是链接: http : //www.techonthenet.com/oracle/sequences.php

Oracle Database 12c引入了Identity,一个自动增量(系统生成)列。 在以前的数据库版本(直到11g)中,通常通过创build序列和触发器来实现标识。 从12c开始,您可以创build自己的表并将必须生成的列定义为标识。

以下文章解释了如何使用它:

标识列 – Oracle Database 12c中的新条目

当你想要序列号,任何人都可以很容易地阅读/记住/理解,可以使用TriggerSequence 。 但是如果你不想通过这种方式来pipe理ID列(比如emp_id),并且这个列的值不是很大,那么你可以在表创build时使用SYS_GUID()来获得像这样的Auto Increment。

 CREATE TABLE <table_name> (emp_id RAW(16) DEFAULT SYS_GUID() PRIMARY KEY, name VARCHAR2(30)); 

现在你的emp_id列将接受“全局唯一标识符值”。 你可以通过忽略这个emp_id列来在表中插入值。

 INSERT INTO <table_name> (name) VALUES ('name value'); 

所以,它会为您的emp_id列插入唯一的值。

从Oracle 12c开始,有两种方法支持Identity列:

  1. Sequence + Table – 在这个解决scheme中,您仍然像往常一样创build一个序列,然后使用以下DDL:

    CREATE TABLE MyTable(ID NUMBER DEFAULT MyTable_Seq.NEXTVAL ,…)

  2. 仅表格 – 在此解决scheme中,没有明确指定序列。 你会使用下面的DDL:

    CREATE TABLE MyTable(ID NUMBER GENERATED AS IDENTITY ,…)

如果你用第一种方式向后兼容现有的做事方式。 第二个更简单一些,与其他RDMS系统更接近。

它被称为Identity Columns ,它只能从Oracle Oracle 12c中获得

 CREATE TABLE identity_test_tab ( id NUMBER GENERATED ALWAYS AS IDENTITY, description VARCHAR2 (30) ); 

插入Identity Columns示例如下

 INSERT INTO identity_test_tab (description) VALUES ('Just DESCRIPTION'); 

1行创build。

你不能像下面那样插入

 INSERT INTO identity_test_tab (id, description) VALUES (NULL, 'ID=NULL and DESCRIPTION'); 

第1行的错误:ORA-32795:无法插入生成的总是标识列

 INSERT INTO identity_test_tab (id, description) VALUES (999, 'ID=999 and DESCRIPTION'); 

第1行的错误:ORA-32795:无法插入生成的总是标识列

有用的链接

这里是完整的自动增量exception/error handling的解决scheme,这个解决scheme是向后兼容的,将在11g和12c上工作,特别是在应用程序正在生产中。

请用您的相应表格名称replace“TABLE_NAME”

 --checking if table already exisits BEGIN EXECUTE IMMEDIATE 'DROP TABLE TABLE_NAME'; EXCEPTION WHEN OTHERS THEN NULL; END; / --creating table CREATE TABLE TABLE_NAME ( ID NUMBER(10) PRIMARY KEY NOT NULL, . . . ); --checking if sequence already exists BEGIN EXECUTE IMMEDIATE 'DROP SEQUENCE TABLE_NAME_SEQ'; EXCEPTION WHEN OTHERS THEN NULL; END; --creating sequence / CREATE SEQUENCE TABLE_NAME_SEQ START WITH 1 INCREMENT BY 1 MINVALUE 1 NOMAXVALUE NOCYCLE CACHE 2; --granting rights as per required user group / GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE_NAME TO USER_GROUP; -- creating trigger / CREATE OR REPLACE TRIGGER TABLE_NAME_TS BEFORE INSERT OR UPDATE ON TABLE_NAME FOR EACH ROW BEGIN -- auto increment column SELECT TABLE_NAME_SEQ.NextVal INTO :New.ID FROM dual; -- You can also put some other required default data as per need of your columns, for example SELECT SYS_CONTEXT('USERENV', 'SESSIONID') INTO :New.SessionID FROM dual; SELECT SYS_CONTEXT('USERENV','SERVER_HOST') INTO :New.HostName FROM dual; SELECT SYS_CONTEXT('USERENV','OS_USER') INTO :New.LoginID FROM dual; . . . END; / 

这是我在现有的表和列(名为id)上做到的:

 UPDATE table SET id=ROWNUM; DECLARE maxval NUMBER; BEGIN SELECT MAX(id) INTO maxval FROM table; EXECUTE IMMEDIATE 'DROP SEQUENCE table_seq'; EXECUTE IMMEDIATE 'CREATE SEQUENCE table_seq START WITH '|| TO_CHAR(TO_NUMBER(maxval)+1) ||' INCREMENT BY 1 NOMAXVALUE'; END; CREATE TRIGGER table_trigger BEFORE INSERT ON table FOR EACH ROW BEGIN :new.id := table_seq.NEXTVAL; END; 
  create trigger t1_trigger before insert on AUDITLOGS for each row begin select t1_seq.nextval into :new.id from dual; end; 

只有我必须更改表名(AUDITLOGS)与您的表名和new.id与new.column_name

 FUNCTION GETUNIQUEID_2 RETURN VARCHAR2 AS v_curr_id NUMBER; v_inc NUMBER; v_next_val NUMBER; pragma autonomous_transaction; begin CREATE SEQUENCE sequnce START WITH YYMMDD0000000001 INCREMENT BY 1 NOCACHE select sequence.nextval into v_curr_id from dual; if(substr(v_curr_id,0,6)= to_char(sysdate,'yymmdd')) then v_next_val := to_number(to_char(SYSDATE+1, 'yymmdd') || '0000000000'); v_inc := v_next_val - v_curr_id; execute immediate ' alter sequence sequence increment by ' || v_inc ; select sequence.nextval into v_curr_id from dual; execute immediate ' alter sequence sequence increment by 1'; else dbms_output.put_line('exception : file not found'); end if; RETURN 'ID'||v_curr_id; END; 
 FUNCTION UNIQUE2( seq IN NUMBER ) RETURN VARCHAR2 AS i NUMBER := seq; s VARCHAR2(9); r NUMBER(2,0); BEGIN WHILE i > 0 LOOP r := MOD( i, 36 ); i := ( i - r ) / 36; IF ( r < 10 ) THEN s := TO_CHAR(r) || s; ELSE s := CHR( 55 + r ) || s; END IF; END LOOP; RETURN 'ID'||LPAD( s, 14, '0' ); END; 

也许只是试试这个简单的脚本:

http://www.hlavaj.sk/ai.php

结果是:

 CREATE SEQUENCE TABLE_PK_SEQ; CREATE OR REPLACE TRIGGER TR_SEQ_TABLE BEFORE INSERT ON TABLE FOR EACH ROW BEGIN SELECT TABLE_PK_SEQ.NEXTVAL INTO :new.PK FROM dual; END;