如何在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_GUID
是RAW(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,2,3,….
- GUID 。 全局唯一标识符,作为
RAW
数据types。 - 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中的新条目
当你想要序列号,任何人都可以很容易地阅读/记住/理解,可以使用Trigger
和Sequence
。 但是如果你不想通过这种方式来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列:
-
Sequence + Table – 在这个解决scheme中,您仍然像往常一样创build一个序列,然后使用以下DDL:
CREATE TABLE MyTable(ID NUMBER DEFAULT MyTable_Seq.NEXTVAL ,…)
-
仅表格 – 在此解决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; /
oracle在12c中有序列和标识列
http://www.oracle-base.com/articles/12c/identity-columns-in-oracle-12cr1.php#identity-columns
我发现这个,但不知道什么RDB 7是technetwork/products/rdb/0307-identity-columns-128126.pdf
这是我在现有的表和列(名为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;
也许只是试试这个简单的脚本:
结果是:
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;