SQLite understøtter en meget begrænset delmængde af ALTER TABLE
udmelding. De eneste ting du kan gøre med ALTER TABLE
i SQLite omdøbes en tabel, omdøber en kolonne i en tabel eller tilføjer en ny kolonne til en eksisterende tabel.
Du kan med andre ord ikke bruge ALTER TABLE
at tilføje en fremmednøgle til en eksisterende tabel, som du kan i andre databasestyringssystemer.
Derfor er den eneste måde, du kan "føje" en fremmednøgle til en eksisterende tabel i SQLite, ved at oprette en ny tabel med en fremmednøgle og derefter overføre dataene til den nye tabel.
Der er mere end én måde at gøre dette på, men der er en anbefalet måde.
Den anbefalede måde
SQLite-dokumentationen anbefaler en 12-trins proces til at lave skemaændringer i en tabel.
I forbindelse med denne artikel vil vi kun beskæftige os med tilføjelse af en fremmednøgle.
For at gøre det lidt realistisk, sørger vi for, at tabellen allerede indeholder data.
Original tabel uden fremmednøgle
Lad os først oprette en tabel uden en fremmednøgle og udfyld den med data.
CREATE TABLE Types(
TypeId INTEGER PRIMARY KEY,
Type
);
CREATE TABLE Pets(
PetId INTEGER PRIMARY KEY,
PetName,
TypeId
);
INSERT INTO Types VALUES
( NULL, 'Dog' ),
( NULL, 'Cat' ),
( NULL, 'Parakeet' ),
( NULL, 'Hamster' );
INSERT INTO Pets VALUES
( NULL, 'Brush', 3 ),
( NULL, 'Tweet', 3 ),
( NULL, 'Yelp', 1 ),
( NULL, 'Woofer', 1 ),
( NULL, 'Fluff', 2 );
Faktisk, her oprettede jeg to tabeller og udfyldte dem med data. To tabeller, fordi én (Typer ) vil have den primære nøgle og den anden (Kæledyr ) vil have fremmednøglen.
Bemærk, at jeg ikke oprettede en fremmednøgle.
Vi kan bekræfte, at der ikke er nogen fremmednøgler ved at køre følgende kommando:
PRAGMA foreign_key_list(Pets);
I mit tilfælde får jeg følgende resultat:
(Det er tomt, fordi der ikke er nogen fremmednøglebegrænsninger på denne tabel.)
Lad os nu "tilføje" en fremmednøgle.
Tilføj fremmednøgle
Følgende kode tilføjer en fremmednøgle til vores tabel ved at oprette en ny tabel med en fremmednøglebegrænsning, overføre dataene til den tabel, slette den oprindelige tabel og derefter omdøbe den nye tabel til navnet på den oprindelige tabel.
PRAGMA foreign_keys = OFF;
BEGIN TRANSACTION;
CREATE TABLE Pets_new(
PetId INTEGER PRIMARY KEY,
PetName,
TypeId,
FOREIGN KEY(TypeId) REFERENCES Types(TypeId)
);
INSERT INTO Pets_new SELECT * FROM Pets;
DROP TABLE Pets;
ALTER TABLE Pets_new RENAME TO Pets;
COMMIT;
PRAGMA foreign_keys = ON;
Færdig.
Hvis du har brug for at rekonstruere indekser, triggere eller visninger, skal du gøre det efter ALTER TABLE
sætning, der omdøber tabellen (lige før COMMIT
).
Lad os nu tjekke tabellen for fremmednøglebegrænsninger igen.
.mode line
PRAGMA foreign_key_list(Pets);
Resultat (ved hjælp af lodret output):
id = 0 seq = 0 table = Types from = TypeId to = TypeId on_update = NO ACTION on_delete = NO ACTION match = NONE
Denne gang kan vi se detaljerne om den fremmede nøgle-begrænsning.
Bemærk, at den første linje i min kommando (.mode line
) har intet at gøre med at oprette en fremmednøgle. Jeg har kun lagt det der for at ændre den måde, min terminal udsender resultatet på (så du ikke behøver at rulle sidelæns for at se resultatet).
En alternativ metode
Når du ser på det foregående eksempel, tænker du måske, at der er en mere effektiv måde at gøre det på. For eksempel kan du gøre det sådan her:
PRAGMA foreign_keys = OFF;
BEGIN TRANSACTION;
ALTER TABLE Pets RENAME TO Pets_old;
CREATE TABLE Pets(
PetId INTEGER PRIMARY KEY,
PetName,
TypeId,
FOREIGN KEY(TypeId) REFERENCES Types(TypeId)
);
INSERT INTO Pets SELECT * FROM Pets_old;
DROP TABLE Pets_old;
COMMIT;
PRAGMA foreign_keys = ON;
Og det er sandt. Med mit eksempel fungerer denne metode lige så godt.
Men denne metode har også potentialet til at ødelægge referencer til tabellen i alle eksisterende triggere, visninger og fremmednøglebegrænsninger.
Så hvis din tabel allerede har eksisterende triggere, visninger eller fremmednøglebegrænsninger, er det sandsynligvis mere sikkert at bruge den anbefalede metode.