Con grande frustrazione degli amministratori di database in tutto il mondo, prima della versione 12c di Oracle a metà del 2014, Oracle semplicemente non aveva la capacità intrinseca di generare colonne con incremento automatico all'interno di uno schema di tabella. Sebbene le ragioni di questa decisione progettuale possano essere solo intuite, la buona notizia è che anche per gli utenti su sistemi Oracle precedenti, esiste una possibile soluzione alternativa per aggirare questa trappola e creare la propria colonna di chiave primaria con incremento automatico.
Creazione di una sequenza
Il primo passo è creare una SEQUENCE
nel database, che è un oggetto dati a cui più utenti possono accedere per generare automaticamente valori incrementati. Come discusso nella documentazione, una sequenza in Oracle impedisce la creazione simultanea di valori duplicati perché più utenti sono effettivamente costretti a "fare a turno" prima che ogni elemento sequenziale venga generato.
Ai fini della creazione di una chiave primaria univoca per una nuova tabella, dobbiamo prima CREATE
la tabella che useremo:
CREATE TABLE books (
id NUMBER(10) NOT NULL,
title VARCHAR2(100) NOT NULL
);
Quindi dobbiamo aggiungere una PRIMARY KEY
vincolo:
ALTER TABLE books
ADD (
CONSTRAINT books_pk PRIMARY KEY (id)
);
Infine, creeremo la nostra SEQUENCE
che verrà utilizzato in seguito per generare effettivamente il valore univoco auto incrementato.
CREATE SEQUENCE books_sequence;
Aggiunta di un trigger
Mentre abbiamo il nostro tavolo creato e pronto per l'uso, la nostra sequenza finora è solo seduta lì ma non viene mai utilizzata. Qui è dove TRIGGERS
entra.
Simile a un event
nei moderni linguaggi di programmazione, un TRIGGER
in Oracle è una procedura memorizzata che viene eseguita quando si verifica un evento particolare.
Tipicamente un TRIGGER
verrà configurato per attivarsi quando una tabella viene aggiornata o un record viene eliminato, fornendo un po' di pulizia quando necessario.
Nel nostro caso, vogliamo eseguire il nostro TRIGGER
prima di INSERT
nei nostri books
tabella, assicurando la nostra SEQUENCE
viene incrementato e quel nuovo valore viene passato alla nostra colonna della chiave primaria.
CREATE OR REPLACE TRIGGER books_on_insert
BEFORE INSERT ON books
FOR EACH ROW
BEGIN
SELECT books_sequence.nextval
INTO :new.id
FROM dual;
END;
Qui stiamo creando (o sostituendo se esiste) il TRIGGER
denominato books_on_insert
e specificando che vogliamo che il trigger si attivi BEFORE INSERT
si verifica per i books
tabella e per essere applicabile a tutte le righe in essa contenute.
Il "codice" del trigger stesso è abbastanza semplice:SELECT
il valore incrementale successivo dal nostro books_sequence
creato in precedenza SEQUENCE
e inserendolo nel :new
record dei books
tabella nel .id
specificato campo.
Nota:il FROM dual
parte è necessaria per completare una query corretta ma è effettivamente irrilevante. Il dual
table è solo una singola riga fittizia di dati e viene aggiunta, in questo caso, solo così può essere ignorata e possiamo invece eseguire la funzione di sistema del nostro trigger piuttosto che restituire dati di qualche tipo.
Colonne IDENTITY
IDENTITY
le colonne sono state introdotte in Oracle 12c, consentendo una semplice funzionalità di incremento automatico nelle versioni moderne di Oracle.
Usando il IDENTITY
colonna è funzionalmente simile a quella di altri sistemi di database. Ricreare i nostri books
sopra schema della tabella nel moderno Oracle 12c o versioni successive, useremmo semplicemente la seguente definizione di colonna.
CREATE TABLE books (
id NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY,
title VARCHAR2(100) NOT NULL
);