¿Cómo crear id con INCREMENTO AUTOMÁTICO en Oracle?


Parece que no hay ningún concepto de AUTO_INCREMENT en Oracle, hasta e incluyendo la versión 11g.

¿Cómo puedo crear una columna que se comporta como incremento automático en Oracle 11g?

Author: Gurwinder Singh, 2012-07-02

16 answers

No hay tal cosa como "auto_increment" o "identidad" columnas en Oracle como de Oracle 11g. Sin embargo, puede modelarlo fácilmente con una secuencia y un disparador:

Definición de la tabla:

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;

Definición del disparador:

CREATE OR REPLACE TRIGGER dept_bir 
BEFORE INSERT ON departments 
FOR EACH ROW

BEGIN
  SELECT dept_seq.NEXTVAL
  INTO   :new.id
  FROM   dual;
END;
/

ACTUALIZACIÓN:

IDENTITY columna ahora está disponible en Oracle 12c:

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

O especificar valores de inicio e incremento, también evitando cualquier inserción en la columna de identidad (GENERATED ALWAYS) (de nuevo, Oracle 12c+ solamente)

create table t1 (
    c1 NUMBER GENERATED ALWAYS as IDENTITY(START with 1 INCREMENT by 1),
    c2 VARCHAR2(10)
    );
 467
Author: Eugenio Cuevas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-08 07:40:03

SYS_GUID devuelve un GUID a un ID global único. A SYS_GUID es un RAW(16). No genera un valor numérico incremental.

Si desea crear una clave numérica incremental, querrá crear una secuencia.

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

Entonces usarías esa secuencia en tu declaración INSERT

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

O puede definir un disparador que rellene automáticamente el valor de la clave primaria utilizando la secuencia

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;

Si está utilizando Oracle 11.1 o más tarde, puede simplificar un poco el disparador

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

Si realmente quieres usar SYS_GUID

CREATE TABLE table_name (
  primary_key_column raw(16) default sys_guid() primary key,
  <<other columns>>
)
 78
Author: Justin Cave,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-09 12:28:08

En Oracle 12c en adelante se podría hacer algo como,

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

Y en 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;
/
 40
Author: Nisar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-06 16:03:43

Aquí hay tres sabores:

  1. numérico. Simple aumento de valor numérico, por ejemplo, 1,2,3,....
  2. GUID . global univeral identifier, as a RAW datatype.
  3. GUID (cadena) . Igual que el anterior, pero como una cadena que podría ser más fácil de manejar en algunos idiomas.

x es la columna de identidad. Sustituya FOO por el nombre de la tabla en cada uno de los ejemplos.

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

Actualización:

Oracle 12c presenta estos dos variantes que no dependen de los disparadores:

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

El primero utiliza una secuencia de la manera tradicional; el segundo gestiona el valor internamente.

 31
Author: Mark Harrison,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-24 16:38:16

Suponiendo que se refiere a una columna como la columna de identidad de SQL Server?

En Oracle, se utiliza una SECUENCIA para lograr la misma funcionalidad. Veré si puedo encontrar un buen enlace y publicarlo aquí.

Actualización: parece que lo encontraste tú mismo. Aquí está el enlace de todos modos: http://www.techonthenet.com/oracle/sequences.php

 7
Author: Phil Sandler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-01-12 23:44:50

Oracle Database 12c introdujo Identity, una columna auto-incremental (generada por el sistema). En las versiones anteriores de la base de datos (hasta 11g), por lo general se implementa una identidad mediante la creación de una Secuencia y un Disparador. A partir de 12c, puede crear su propia Tabla y definir la columna que debe generarse como Identidad.

El siguiente artículo explica cómo usarlo:

Columnas de identidad-Una nueva entrada en Oracle Database 12c

 7
Author: Corrado Piola,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-05 13:06:48

Trigger y Sequence se puede usar cuando se desea un número serializado que cualquiera pueda leer/recordar/entender fácilmente. Pero si no desea administrar la columna ID (como emp_id) de esta manera, y el valor de esta columna no es mucho considerable, puede usar SYS_GUID() en la creación de la tabla para obtener un Incremento Automático como este.

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

Ahora su columna emp_id aceptará "valor de identificador único global". puede insertar valor en la tabla ignorando la columna emp_id de esta manera.

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

Por lo tanto, se insertará valor único para su columna emp_id.

 5
Author: N J,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-18 06:08:37

A partir de Oracle 12c hay soporte para columnas de identidad de una de dos maneras:

  1. Secuencia + Tabla - En esta solución todavía se crea una secuencia como lo haría normalmente, luego se utiliza el siguiente DDL:

    CREAR TABLA MyTable (ID NUMBER POR DEFECTO MyTable_Seq.NEXTVAL, ...)

  2. Solo Tabla - En esta solución no se especifica ninguna secuencia explícitamente. Usarías el siguiente DDL:

    CREAR TABLA MyTable (ID NUMBER GENERATED AS IDENTITY ,...)

Si utiliza la primera forma, es compatible con la forma existente de hacer las cosas. El segundo es un poco más sencillo y está más en línea con el resto de los sistemas RDMS que existen.

 4
Author: Nate Zaugg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-24 15:53:29

Se llama Identity Columns y está disponible solo desde oracle Oracle 12c

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

Ejemplo de insertar en Identity Columns como se indica a continuación

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

1 fila creada.

NO se puede hacer insertar como a continuación

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

ERROR en la línea 1: ORA-32795: no se puede insertar en un siempre generado columna de identidad

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

ERROR en la línea 1: ORA-32795: no se puede insertar en un siempre generado columna de identidad

Útil link

 3
Author: sam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-10 12:44:26

Aquí está la solución completa w.r.t exception/error handling for auto increment, esta solución es compatible con versiones anteriores y funcionará en 11g y 12c, específicamente si la aplicación está en producción.

Por favor, reemplace 'TABLE_NAME' con su nombre de tabla apropiado

--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
Author: emkays,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-17 11:12:47
 0
Author: Kalpesh Soni,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-08-27 21:47:23

Así es como hice esto en una tabla y columna existente (llamada 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;
 0
Author: ether6,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-18 23:06:13
  create trigger t1_trigger
  before insert on AUDITLOGS
  for each row
   begin
     select t1_seq.nextval into :new.id from dual;
   end;

Solo tengo que cambiar el nombre de la tabla (AUDITLOGS) con el nombre de la tabla y new.id con nuevo.column_name

 -1
Author: abhishek ringsia,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-21 06:46:21
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;
 -1
Author: kumar venkatesan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-02 11:22:07
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;
 -1
Author: kumar venkatesan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-02 11:25:31

Tal vez solo pruebe este sencillo script:

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

El resultado es:

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;
 -2
Author: Martin Hlavaj,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-02 09:24:22