Sembra che non vi sia alcun concetto di AUTO_INCREMENT in Oracle, fino alla versione 11g inclusa.
Come posso creare una colonna che si comporta come l'incremento automatico in Oracle 11g?
Sembra che non vi sia alcun concetto di AUTO_INCREMENT in Oracle, fino alla versione 11g inclusa.
Come posso creare una colonna che si comporta come l'incremento automatico in Oracle 11g?
Risposte:
Non esistono colonne "auto_increment" o "identity" in Oracle a partire da Oracle 11g . Tuttavia, puoi modellarlo facilmente con una sequenza e un trigger:
Definizione della tabella:
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;
Definizione del trigger:
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 colonna è ora disponibile su Oracle 12c:
create table t1 (
c1 NUMBER GENERATED by default on null as IDENTITY,
c2 VARCHAR2(10)
);
o specificare i valori iniziali e incrementali, impedendo anche qualsiasi inserimento nella colonna identità ( GENERATED ALWAYS
) (di nuovo, solo Oracle 12c +)
create table t1 (
c1 NUMBER GENERATED ALWAYS as IDENTITY(START with 1 INCREMENT by 1),
c2 VARCHAR2(10)
);
In alternativa, Oracle 12 consente anche di utilizzare una sequenza come valore predefinito:
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));
dept_seq
viene!
SELECT .. INTO
nel trigger che si può semplicemente fare :new.id := dept_seq.NEXTVAL;
.
SYS_GUID
restituisce un GUID: un ID univoco globale. A SYS_GUID
è a RAW(16)
. Non genera un valore numerico incrementale.
Se vuoi creare un tasto numerico incrementale, ti consigliamo di creare una sequenza.
CREATE SEQUENCE name_of_sequence
START WITH 1
INCREMENT BY 1
CACHE 100;
Dovresti quindi utilizzare quella sequenza nella tua INSERT
dichiarazione
INSERT INTO name_of_table( primary_key_column, <<other columns>> )
VALUES( name_of_sequence.nextval, <<other values>> );
Oppure puoi definire un trigger che popola automaticamente il valore della chiave primaria usando la sequenza
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;
Se si utilizza Oracle 11.1 o versioni successive, è possibile semplificare un po 'il trigger
CREATE OR REPLACE TRIGGER trigger_name
BEFORE INSERT ON table_name
FOR EACH ROW
BEGIN
:new.primary_key_column := name_of_sequence.nextval;
END;
Se vuoi davvero usarlo SYS_GUID
CREATE TABLE table_name (
primary_key_column raw(16) default sys_guid() primary key,
<<other columns>>
)
CACHE 100; in CREATE SEQUENCE name_of_sequence START WITH 1 INCREMENT BY 1 CACHE 100;
fare?
SYS_GUID()
è a RAW(16)
, non 32.
SYS_GUID
documentazione dichiara raw(32)
che mi ha confuso.
In Oracle 12c in poi potresti fare qualcosa del tipo,
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)
);
E 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;
/
IDENTITY
esempio è molto più chiaro in questa risposta.
WHEN (new.MAP_ID IS NULL)
non è nella risposta accettata. Upvoted.
WHEN ( new.MAP_ID is null)
in questo caso non è un buon codice ed è già spiegato nella sezione commenti da @ABCade sotto la risposta accettata .. leggi;)
CREATE OR REPLACE TRIGGER
a END;
, ottengo una finestra "Enter Binds". Se faccio clic su "Applica" e non faccio nient'altro in quella finestra, e quindi eseguo il ALTER TRIGGER
comando, tutto va bene, ma vorrei che ci fosse un modo per eliminare programmaticamente quel pop-up ed eseguire tutto insieme. Se lo provi del tutto, ottieni PLS-00103: Encountered the symbol 'ALTER'
e non piace EXECUTE IMMEDIATE
neanche (lo stesso errore, Encountered the symbol 'EXECUTE'
invece lo dice solo ).
[42000][907] ORA-00907: missing right parenthesis
eseguendo la versione per Oracle 12c in poi. Qualche idea ?
Ecco tre gusti:
RAW
tipo di dati.x
è la colonna identità. Sostituisci FOO
con il nome della tabella in ciascuno degli esempi.
-- 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;
/
aggiornare:
Oracle 12c introduce queste due varianti che non dipendono dai trigger:
create table mytable(id number default mysequence.nextval);
create table mytable(id number generated as identity);
Il primo usa una sequenza in modo tradizionale; il secondo gestisce il valore internamente.
Supponendo che intendi una colonna come la colonna dell'identità di SQL Server?
In Oracle, si utilizza una SEQUENZA per ottenere la stessa funzionalità. Vedrò se riesco a trovare un buon link e pubblicarlo qui.
Aggiornamento: sembra che tu l'abbia trovato tu stesso. Ecco comunque il link: http://www.techonthenet.com/oracle/sequences.php
Oracle Database 12c ha introdotto Identity, una colonna auto-incrementale (generata dal sistema). Nelle versioni precedenti del database (fino a 11g), di solito si implementa un'identità creando una sequenza e un trigger. Dal 12c in poi, puoi creare la tua tabella e definire la colonna che deve essere generata come identità.
Il seguente articolo spiega come usarlo:
Trigger
e Sequence
può essere utilizzato quando si desidera un numero seriale che chiunque può facilmente leggere / ricordare / comprendere. Ma se non vuoi gestire la colonna ID (come emp_id) in questo modo e il valore di questa colonna non è molto considerevole, puoi usare la SYS_GUID()
Creazione tabella per ottenere l'incremento automatico in questo modo.
CREATE TABLE <table_name>
(emp_id RAW(16) DEFAULT SYS_GUID() PRIMARY KEY,
name VARCHAR2(30));
Ora la tua emp_id
colonna accetterà "valore identificatore univoco globale". puoi inserire valore nella tabella ignorando la colonna emp_id in questo modo.
INSERT INTO <table_name> (name) VALUES ('name value');
Quindi, inserirà un valore univoco nella emp_id
colonna.
SYS_GUID()
suoi valori ID saranno ?
A partire da Oracle 12c esiste il supporto per le colonne Identity in due modi:
Sequenza + Tabella - In questa soluzione crei comunque una sequenza come faresti normalmente, quindi usi il seguente DDL:
CREATE TABLE MyTable (ID NUMBER DEFAULT MyTable_Seq.NEXTVAL , ...)
Solo tabella : in questa soluzione non viene specificata esplicitamente alcuna sequenza. Dovresti usare il seguente DDL:
CREATE TABLE MyTable (NUMERO ID GENERATO COME IDENTITÀ , ...)
Se usi il primo modo, è retrocompatibile con il modo esistente di fare le cose. Il secondo è un po 'più semplice ed è più in linea con il resto dei sistemi RDMS disponibili.
si chiama Identity Columns
ed è disponibile solo da Oracle Oracle 12c
CREATE TABLE identity_test_tab
(
id NUMBER GENERATED ALWAYS AS IDENTITY,
description VARCHAR2 (30)
);
esempio di inserimento Identity Columns
come di seguito
INSERT INTO identity_test_tab (description) VALUES ('Just DESCRIPTION');
1 riga creata.
NON è possibile inserire come di seguito
INSERT INTO identity_test_tab (id, description) VALUES (NULL, 'ID=NULL and DESCRIPTION');
ERRORE alla riga 1: ORA-32795: impossibile inserire in una colonna di identità sempre generata
INSERT INTO identity_test_tab (id, description) VALUES (999, 'ID=999 and DESCRIPTION');
ERRORE alla riga 1: ORA-32795: impossibile inserire in una colonna di identità sempre generata
Ecco una soluzione completa per la gestione di eccezioni / errori per l'incremento automatico, questa soluzione è retrocompatibile e funzionerà su 11g e 12c, in particolare se l'applicazione è in produzione.
Sostituisci "TABLE_NAME" con il nome della tabella appropriato
--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;
/
Ecco come l'ho fatto su una tabella e una colonna esistenti (denominata 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;
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;
l'oracolo ha sequenze E colonne di identità nel 12c
http://www.oracle-base.com/articles/12c/identity-columns-in-oracle-12cr1.php#identity-columns
Ho trovato questo, ma non sono sicuro di cosa sia rdb 7 http://www.oracle.com/technetwork/products/rdb/0307-identity-columns-128126.pdf
create trigger t1_trigger
before insert on AUDITLOGS
for each row
begin
select t1_seq.nextval into :new.id from dual;
end;
devo solo cambiare il nome della tabella (AUDITLOGS) con il nome della tua tabella e new.id con new.column_name
Forse prova questo semplice script:
Il risultato è:
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;
select
nelle moderne versioni Oracle. Puoi semplicemente usare:new.pk := TABLE_PK_SEQ.NEXTVAL
BEFORE INSERT
trigger sul tavolo ed estrarre i valori da una sequenza per creare l'auto-incremento