Till stor frustration för databasadministratörer världen över, innan Oracle version 12c i mitten av 2014, hade Oracle helt enkelt ingen inneboende förmåga att generera automatiskt inkrementerande kolumner i ett tabellschema. Även om orsakerna till detta designbeslut bara kan gissas till, är den goda nyheten att även för användare på äldre Oracle-system finns det en möjlig lösning för att kringgå denna fallgrop och skapa din egen automatiskt inkrementerade primärnyckelkolumn.
Skapa en sekvens
Det första steget är att skapa en SEQUENCE
i din databas, som är ett dataobjekt som flera användare kan komma åt för att automatiskt generera inkrementerade värden. Som diskuteras i dokumentationen förhindrar en sekvens i Oracle att dubbletter av värden skapas samtidigt eftersom flera användare effektivt tvingas "turas om" innan varje sekventiell post genereras.
För att skapa en unik primärnyckel för en ny tabell måste vi först CREATE
tabellen vi kommer att använda:
CREATE TABLE books (
id NUMBER(10) NOT NULL,
title VARCHAR2(100) NOT NULL
);
Därefter måste vi lägga till en PRIMARY KEY
begränsning:
ALTER TABLE books
ADD (
CONSTRAINT books_pk PRIMARY KEY (id)
);
Slutligen skapar vi vår SEQUENCE
som kommer att användas senare för att faktiskt generera det unika, automatiskt inkrementerade värdet.
CREATE SEQUENCE books_sequence;
Lägga till en utlösare
Medan vi har vårt bord skapat och redo att köra, så sitter vår sekvens hittills bara där men kommer aldrig att användas. Det är här TRIGGERS
kom in.
Liknar en event
i moderna programmeringsspråk, en TRIGGER
i Oracle är en lagrad procedur som exekveras när en viss händelse inträffar.
Vanligtvis en TRIGGER
kommer att konfigureras för att aktiveras när en tabell uppdateras eller en post raderas, vilket ger lite rensning vid behov.
I vårt fall vill vi köra vår TRIGGER
före INSERT
i våra books
tabell, vilket säkerställer vår SEQUENCE
ökas och det nya värdet skickas till vår primärnyckelkolumn.
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;
Här skapar vi (eller ersätter om den finns) TRIGGER
heter books_on_insert
och anger att vi vill att utlösaren ska aktiveras BEFORE INSERT
förekommer för books
tabell och att vara tillämplig på alla rader däri.
"Koden" för själva triggern är ganska enkel:Vi SELECT
nästa inkrementella värde från vår tidigare skapade books_sequence
SEQUENCE
, och infoga det i :new
register över books
tabellen i den angivna .id
fältet.
Obs:FROM dual
del är nödvändig för att slutföra en korrekt fråga men är faktiskt irrelevant. dual
Tabellen är bara en enda dummyrad med data och läggs till, i det här fallet, bara så att den kan ignoreras och vi istället kan utföra systemfunktionen för vår utlösare istället för att returnera data av något slag.
IDENTITY-kolumner
IDENTITY
kolumner introducerades i Oracle 12c, vilket möjliggör enkel automatisk inkrementfunktion i moderna versioner av Oracle.
Använda IDENTITY
kolumnen är funktionellt lik den i andra databassystem. Återskapa våra ovanstående books
tabellschema i moderna Oracle 12c eller högre, skulle vi helt enkelt använda följande kolumndefinition.
CREATE TABLE books (
id NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY,
title VARCHAR2(100) NOT NULL
);