Es scheint, dass es in Oracle bis einschließlich Version 11g kein Konzept für AUTO_INCREMENT gibt.
Wie kann ich eine Spalte erstellen, die sich in Oracle 11g wie eine automatische Inkrementierung verhält?
In Oracle gibt es ab Oracle 11g keine "auto_increment" - oder "identity" -Spalten mehr. Sie können es jedoch einfach mit einer Sequenz und einem Trigger modellieren:
Tabellendefinition:
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;
Triggerdefinition:
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
Spalte ist jetzt in Oracle 12c verfügbar:
create table t1 (
c1 NUMBER GENERATED by default on null as IDENTITY,
c2 VARCHAR2(10)
);
oder geben Sie Start- und Inkrementierungswerte an, um auch das Einfügen in die Identitätsspalte (GENERATED ALWAYS
) zu verhindern (auch hier nur Oracle 12c +)
create table t1 (
c1 NUMBER GENERATED ALWAYS as IDENTITY(START with 1 INCREMENT by 1),
c2 VARCHAR2(10)
);
Alternativ kann in Oracle 12 auch eine Sequenz als Standardwert verwendet werden:
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
gibt eine GUID zurück - eine global eindeutige ID. Ein SYS_GUID
ist ein RAW(16)
. Es wird kein inkrementierender numerischer Wert generiert.
Wenn Sie einen inkrementellen numerischen Schlüssel erstellen möchten, müssen Sie eine Sequenz erstellen.
CREATE SEQUENCE name_of_sequence
START WITH 1
INCREMENT BY 1
CACHE 100;
Sie würden dann entweder diese Sequenz in Ihrer INSERT
-Anweisung verwenden
INSERT INTO name_of_table( primary_key_column, <<other columns>> )
VALUES( name_of_sequence.nextval, <<other values>> );
Sie können auch einen Trigger definieren, der den Primärschlüsselwert mithilfe der Sequenz automatisch auffüllt
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;
Wenn Sie Oracle 11.1 oder höher verwenden, können Sie den Trigger etwas vereinfachen
CREATE OR REPLACE TRIGGER trigger_name
BEFORE INSERT ON table_name
FOR EACH ROW
BEGIN
:new.primary_key_column := name_of_sequence.nextval;
END;
Wenn Sie wirklich SYS_GUID
verwenden möchten
CREATE TABLE table_name (
primary_key_column raw(16) default sys_guid() primary key,
<<other columns>>
)
Ab Oracle 12c können Sie Folgendes tun:
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)
);
Und in 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;
/
Hier sind drei Geschmacksrichtungen:
RAW
-Datentyp.x
ist die Identitätsspalte. Ersetzen Sie in jedem Beispiel FOO
durch Ihren Tabellennamen.
-- 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;
/
aktualisieren:
Oracle 12c führt diese beiden Varianten ein, die nicht von Triggern abhängig sind:
create table mytable(id number default mysequence.nextval);
create table mytable(id number generated as identity);
Die erste verwendet eine Sequenz auf traditionelle Weise; Der zweite verwaltet den Wert intern.
Angenommen, Sie meinen eine Spalte wie die SQL Server-Identitätsspalte?
In Oracle verwenden Sie eine SEQUENCE, um dieselbe Funktionalität zu erzielen. Ich werde sehen, ob ich einen guten Link finden und hier posten kann.
Update: Sieht so aus, als hätten Sie es selbst gefunden. Hier ist der Link trotzdem: http://www.techonthenet.com/Oracle/sequences.php
Oracle Database 12c führte Identity ein, eine automatisch inkrementelle (systemgenerierte) Spalte. In früheren Datenbankversionen (bis 11g) implementieren Sie normalerweise eine Identität, indem Sie eine Sequenz und einen Trigger erstellen. Ab 12c können Sie eine eigene Tabelle erstellen und die Spalte definieren, die als Identität generiert werden soll.
Der folgende Artikel erklärt, wie man es benutzt:
Identitätsspalten - Ein neuer Eintrag in Oracle Database 12c
Trigger
und Sequence
können verwendet werden, wenn Sie eine Seriennummer wünschen, die jeder leicht lesen/merken/verstehen kann. Wenn Sie die ID-Spalte (wie emp_id) jedoch nicht auf diese Weise verwalten möchten und der Wert dieser Spalte nicht sehr bedeutend ist, können Sie SYS_GUID()
bei der Tabellenerstellung verwenden, um ein solches automatisches Inkrement zu erhalten.
CREATE TABLE <table_name>
(emp_id RAW(16) DEFAULT SYS_GUID() PRIMARY KEY,
name VARCHAR2(30));
Jetzt akzeptiert Ihre emp_id
-Spalte "global unique identifier value". Sie können einen Wert in die Tabelle einfügen, indem Sie die Spalte emp_id wie folgt ignorieren.
INSERT INTO <table_name> (name) VALUES ('name value');
Es wird also ein eindeutiger Wert in Ihre emp_id
-Spalte eingefügt.
Ab Oracle 12c werden Identitätsspalten auf zwei Arten unterstützt:
Sequenz + Tabelle - In dieser Lösung erstellen Sie immer noch eine Sequenz wie gewohnt und verwenden dann die folgende DDL:
CREATE TABLE MyTable (ID-NUMMER DEFAULT MyTable_Seq.NEXTVAL, ...)
Nur Tabelle - In dieser Lösung wird keine Reihenfolge explizit angegeben. Sie würden die folgende DDL verwenden:
CREATE TABLE MyTable (ID-NUMMER ALS IDENTITÄT GENERIERT, ...)
Wenn Sie die erste Methode verwenden, ist sie abwärtskompatibel mit der vorhandenen Vorgehensweise. Die zweite Variante ist etwas unkomplizierter und passt besser zu den übrigen RDMS-Systemen.
es heißt Identity Columns
und ist verfügbar nur von Oracle Oracle 12c
CREATE TABLE identity_test_tab
(
id NUMBER GENERATED ALWAYS AS IDENTITY,
description VARCHAR2 (30)
);
beispiel für das Einfügen in Identity Columns
(siehe unten)
INSERT INTO identity_test_tab (description) VALUES ('Just DESCRIPTION');
1 Zeile erstellt.
sie können NICHT wie unten einfügen
INSERT INTO identity_test_tab (id, description) VALUES (NULL, 'ID=NULL and DESCRIPTION');
FEHLER in Zeile 1: ORA-32795: Kann nicht in eine generierte Always-Identity-Spalte eingefügt werden
INSERT INTO identity_test_tab (id, description) VALUES (999, 'ID=999 and DESCRIPTION');
FEHLER in Zeile 1: ORA-32795: Kann nicht in eine generierte Always-Identity-Spalte eingefügt werden
Hier finden Sie eine vollständige Lösung mit Ausnahme-/Fehlerbehandlung für automatisches Inkrementieren. Diese Lösung ist abwärtskompatibel und funktioniert mit 11g und 12c, insbesondere, wenn die Anwendung in Produktion ist.
Ersetzen Sie "TABLE_NAME" durch Ihren entsprechenden Tabellennamen
--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;
So habe ich das für eine vorhandene Tabelle und Spalte (benannte ID) gemacht:
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;