Il semble qu’il n’existe pas de concept AUTO_INCREMENT dans Oracle, jusqu’à la version 11g incluse.
Comment créer une colonne qui se comporte comme une incrémentation automatique dans Oracle 11g?
Il n’existe pas de colonnes "auto_increment" ou "identité" dans Oracle à partir de Oracle 11g . Cependant, vous pouvez facilement le modéliser avec une séquence et un déclencheur:
Définition du tableau:
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;
Définition du déclencheur:
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
la colonne est maintenant disponible sur Oracle 12c:
create table t1 (
c1 NUMBER GENERATED by default on null as IDENTITY,
c2 VARCHAR2(10)
);
ou spécifier des valeurs de départ et d'incrément, en empêchant également toute insertion dans la colonne d'identité (GENERATED ALWAYS
) (à nouveau, Oracle 12c + uniquement)
create table t1 (
c1 NUMBER GENERATED ALWAYS as IDENTITY(START with 1 INCREMENT by 1),
c2 VARCHAR2(10)
);
Sinon, Oracle 12 permet également d’utiliser une séquence comme valeur par défaut:
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));
_SYS_GUID
_ renvoie un GUID - un ID unique au monde. Un SYS_GUID
est un RAW(16)
. Il ne génère pas de valeur numérique incrémentante.
Si vous souhaitez créer une clé numérique incrémentante, vous devez créer une séquence.
_CREATE SEQUENCE name_of_sequence
START WITH 1
INCREMENT BY 1
CACHE 100;
_
Vous pouvez alors utiliser cette séquence dans votre instruction INSERT
_INSERT INTO name_of_table( primary_key_column, <<other columns>> )
VALUES( name_of_sequence.nextval, <<other values>> );
_
Ou vous pouvez définir un déclencheur qui renseigne automatiquement la valeur de la clé primaire en utilisant la séquence
_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 vous utilisez Oracle 11.1 ou une version ultérieure, vous pouvez simplifier un peu le déclencheur.
_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 vous voulez vraiment utiliser _SYS_GUID
_
_CREATE TABLE table_name (
primary_key_column raw(16) default sys_guid() primary key,
<<other columns>>
)
_
Dans Oracle 12c, vous pouvez faire quelque chose comme:
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)
);
Et dans Oracle (Pré 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;
/
Voici trois saveurs:
RAW
.x
est la colonne d'identité. Remplacez FOO
par le nom de votre table dans chacun des exemples.
-- 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;
/
mise à jour:
Oracle 12c introduit ces deux variantes qui ne dépendent pas de déclencheurs:
create table mytable(id number default mysequence.nextval);
create table mytable(id number generated as identity);
Le premier utilise une séquence de la manière traditionnelle; le second gère la valeur en interne.
En supposant que vous vouliez dire une colonne comme la colonne d’identité SQL Server?
Dans Oracle, vous utilisez une séquence pour obtenir la même fonctionnalité. Je verrai si je peux trouver un bon lien et le poster ici.
Mise à jour: on dirait que vous l'avez trouvé vous-même. Voici le lien quand même: http://www.techonthenet.com/Oracle/sequences.php
Oracle Database 12c a introduit Identity, une colonne auto-incrémentielle (générée par le système). Dans les versions précédentes de la base de données (jusqu'à 11g), vous implémentez généralement une identité en créant une séquence et un déclencheur. À partir de 12c, vous pouvez créer votre propre table et définir la colonne à générer en tant qu'identité.
L'article suivant explique comment l'utiliser:
Colonnes d'identité - Une nouvelle entrée dans Oracle Database 12c
Trigger
et Sequence
peuvent être utilisés lorsque vous voulez un numéro sérialisé que tout le monde peut facilement lire/mémoriser/comprendre. Mais si vous ne souhaitez pas gérer ID Column (comme emp_id) de cette manière et que la valeur de cette colonne n’est pas très considérable, vous pouvez utiliser SYS_GUID()
lors de la création de table pour obtenir l’incrément automatique.
CREATE TABLE <table_name>
(emp_id RAW(16) DEFAULT SYS_GUID() PRIMARY KEY,
name VARCHAR2(30));
Maintenant, votre colonne emp_id
acceptera "la valeur d'identificateur global unique". vous pouvez insérer une valeur dans la table en ignorant la colonne emp_id comme ceci.
INSERT INTO <table_name> (name) VALUES ('name value');
Ainsi, il insérera une valeur unique dans votre colonne emp_id
.
À partir d'Oracle 12c, les colonnes Identity sont prises en charge de deux manières:
Séquence + Table - Dans cette solution, vous créez toujours une séquence comme vous le feriez normalement, puis vous utilisez le DDL suivant:
CREATE TABLE MyTable (NUMERO D'IDENTIFICATION DEFAULT MyTable_Seq.NEXTVAL, ...)
Table Only - Dans cette solution, aucune séquence n'est explicitement spécifiée. Vous utiliseriez le DDL suivant:
CREATE TABLE MyTable (NUMERO D'IDENTIFICATION GENEREE COMME IDENTITÉ, ...)
Si vous utilisez la première manière, elle est rétrocompatible avec la façon de faire existante. Le second est un peu plus simple et s’aligne davantage sur le reste des systèmes RDMS.
il s'appelle Identity Columns
et il est disponible uniquement à partir d'Oracle Oracle 12c
CREATE TABLE identity_test_tab
(
id NUMBER GENERATED ALWAYS AS IDENTITY,
description VARCHAR2 (30)
);
exemple d'insertion dans Identity Columns
comme ci-dessous
INSERT INTO identity_test_tab (description) VALUES ('Just DESCRIPTION');
1 rangée créée.
vous ne pouvez PAS insérer comme ci-dessous
INSERT INTO identity_test_tab (id, description) VALUES (NULL, 'ID=NULL and DESCRIPTION');
ERREUR à la ligne 1: ORA-32795: impossible d'insérer dans une colonne toujours générée.
INSERT INTO identity_test_tab (id, description) VALUES (999, 'ID=999 and DESCRIPTION');
ERREUR à la ligne 1: ORA-32795: impossible d'insérer dans une colonne toujours générée.
Voici une solution complète pour la gestion des exceptions/erreurs avec incrémentation automatique. Cette solution est rétro-compatible et fonctionnera avec les versions 11g et 12c, en particulier si l’application est en production.
Veuillez remplacer "TABLE_NAME" par votre nom de table approprié
--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;
/
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;
Voici comment j'ai fait cela sur une table et une colonne existantes (nommée 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;