首页 文章

如何在Oracle上使用AUTO_INCREMENT创建id?

提问于
浏览
330

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

如何在Oracle 11g中创建一个行为类似自动增量的列?

16 回答

  • -2
    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;
    
  • 79

    从Oracle 11g开始,Oracle中没有"auto_increment"或"identity"列 . 但是,您可以使用序列和触发器轻松地对其进行建模:

    表定义:

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

    更新:

    现在,Oracle 12c上提供了IDENTITY列:

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

    或者,Oracle 12还允许使用序列作为默认值:

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

    SYS_GUID 返回GUID--全局唯一ID . SYS_GUIDRAW(16) . 它不会生成递增的数值 .

    如果要创建递增数字键,则需要创建序列 .

    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>>
    )
    
  • 0

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

    CREATE TABLE MAPS
    (
      MAP_ID INTEGER GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1) NOT NULL,
      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 MAPS_SEQ.NEXTVAL
      INTO   :new.MAP_ID
      FROM   dual;
    END;
    /
    
  • 42
    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;
    
  • 7

    这有三种口味:

    • numeric . 简单地增加数值,例如1,2,3,...

    • GUID . 全局univeral标识符,为 RAW 数据类型 .

    • GUID (string) . 与上面相同,但作为一个字符串,在某些语言中可能更容易处理 .

    x 是标识列 . 在每个示例中用您的表名替换 FOO .

    -- numerical identity, e.g. 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, e.g. 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);
    

    第一个使用传统方式的序列;第二个在内部管理 Value .

  • 1

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

    在Oracle中,您使用SEQUENCE来实现相同的功能 . 我会看看我是否能找到一个好的链接并在此发布 .

    更新:看起来你自己找到了它 . 无论如何这是链接:http://www.techonthenet.com/oracle/sequences.php

  • 5

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

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

    Identity columns - A new entry in Oracle Database 12c

  • -1

    当您想要任何人都可以轻松阅读/记忆/理解的序列号时,可以使用 TriggerSequence . 但是如果你不想通过这种方式管理ID列(比如emp_id),并且这个列的值不是很大,你可以在Table Creation中使用 SYS_GUID() 来获得这样的自动增量 .

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

    现在你的 emp_id 列将接受"globally unique identifier value" . 您可以通过忽略这样的emp_id列在表中插入值 .

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

    因此,它会为您的 emp_id 列插入唯一值 .

  • 5

    从Oracle 12c开始,可以通过以下两种方式之一支持Identity列:

    • 序列表 - 在此解决方案中,您仍然可以像往常一样创建序列,然后使用以下DDL:

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

    • 仅表 - 在此解决方案中,未明确指定序列 . 您将使用以下DDL:

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

    如果您使用第一种方式,它向后兼容现有的做事方式 . 第二个是更直接的,并且与其他RDMS系统更加一致 .

  • 487

    它被称为 Identity Columns ,它可用 only from 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行 .

    你不能像下面这样插入

    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:无法插入生成的始终标识列

    useful link

  • 3

    这是完整的解决方案w.r.t异常/错误处理自动增量,这个解决方案是向后兼容的,将适用于11g和12c,特别是如果应用程序正在 生产环境 中 .

    请使用适当的表名替换“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;
    /
    
  • -1

    这是我在现有表和列(命名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;
    
  • 7
  • 0
    create trigger t1_trigger
      before insert on AUDITLOGS
      for each row
       begin
         select t1_seq.nextval into :new.id from dual;
       end;
    

    只需要用表名更改表名(AUDITLOGS),用new.column_name更改new.id

  • 0

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

    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;
    

相关问题