SQLite ondersteunt een zeer beperkte subset van de ALTER TABLE
uitspraak. Het enige dat u kunt doen met ALTER TABLE
in SQLite is het hernoemen van een tabel, het hernoemen van een kolom binnen een tabel of het toevoegen van een nieuwe kolom aan een bestaande tabel.
Met andere woorden, u kunt ALTER TABLE
niet gebruiken om een externe sleutel toe te voegen aan een bestaande tabel zoals u kunt in andere databasebeheersystemen.
Daarom is de enige manier waarop u een externe sleutel aan een bestaande tabel in SQLite kunt "toevoegen" door een nieuwe tabel met een externe sleutel te maken en vervolgens de gegevens naar de nieuwe tabel over te brengen.
Er is meer dan één manier om dit te doen, maar er is een aanbevolen manier.
De aanbevolen manier
De SQLite-documentatie beveelt een proces van 12 stappen aan voor het aanbrengen van schemawijzigingen in een tabel.
Voor de doeleinden van dit artikel behandelen we alleen het toevoegen van een externe sleutel.
Om het enigszins realistisch te maken, zorgen we ervoor dat de tabel al gegevens bevat.
Originele tabel zonder externe sleutel
Laten we eerst een tabel maken zonder een externe sleutel en vul deze met gegevens.
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 );
Eigenlijk heb ik hier twee tabellen gemaakt en deze gevuld met gegevens. Twee tabellen, omdat één (Typen ) heeft de primaire sleutel en de andere (Huisdieren ) zal de externe sleutel hebben.
Merk op dat ik geen externe sleutel heb gemaakt.
We kunnen controleren of er geen externe sleutels zijn door het volgende commando uit te voeren:
PRAGMA foreign_key_list(Pets);
In mijn geval krijg ik het volgende resultaat:
(Dat is blanco omdat er geen beperkingen zijn voor externe sleutels in deze tabel.)
Laten we nu een externe sleutel "toevoegen".
Externe sleutel toevoegen
De volgende code voegt een externe sleutel toe aan onze tabel door een nieuwe tabel te maken met een externe sleutelbeperking, de gegevens naar die tabel over te brengen, de oorspronkelijke tabel te verwijderen en de nieuwe tabel vervolgens te hernoemen naar de naam van de oorspronkelijke 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;
Klaar.
Als je indexen, triggers of views moet reconstrueren, doe dat dan na de ALTER TABLE
statement dat de tabel hernoemt (net voor COMMIT
).
Laten we nu de tabel opnieuw controleren op beperkingen voor externe sleutels.
.mode line
PRAGMA foreign_key_list(Pets);
Resultaat (met verticale uitvoer):
id = 0 seq = 0 table = Types from = TypeId to = TypeId on_update = NO ACTION on_delete = NO ACTION match = NONE
Deze keer kunnen we de details van de externe sleutelbeperking zien.
Merk op dat de eerste regel van mijn opdracht (.mode line
) heeft niets te maken met het maken van een externe sleutel. Ik heb het daar alleen geplaatst om de manier te veranderen waarop mijn terminal het resultaat uitvoert (zodat je niet zijwaarts hoeft te scrollen om het resultaat te bekijken).
Een alternatieve methode
Als je naar het vorige voorbeeld kijkt, denk je misschien dat er een efficiëntere manier is om dit te doen. U kunt het bijvoorbeeld als volgt doen:
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;
En het is waar. Met mijn voorbeeld werkt deze methode net zo goed.
Maar deze methode heeft ook het potentieel om verwijzingen naar de tabel in bestaande triggers, views en externe sleutelbeperkingen te beschadigen.
Dus als uw tabel al bestaande triggers, weergaven of externe sleutelbeperkingen heeft, is het waarschijnlijk veiliger om de aanbevolen methode te gebruiken.