SQLite unterstützt eine sehr begrenzte Teilmenge von ALTER TABLE
Erklärung. Das Einzige, was Sie mit ALTER TABLE
tun können in SQLite ist das Umbenennen einer Tabelle, das Umbenennen einer Spalte innerhalb einer Tabelle oder das Hinzufügen einer neuen Spalte zu einer bestehenden Tabelle.
Mit anderen Worten, Sie können ALTER TABLE
nicht verwenden um einen Fremdschlüssel zu einer bestehenden Tabelle hinzuzufügen, wie Sie es in anderen Datenbankverwaltungssystemen tun können.
Daher besteht die einzige Möglichkeit, einen Fremdschlüssel zu einer vorhandenen Tabelle in SQLite „hinzuzufügen“, darin, eine neue Tabelle mit einem Fremdschlüssel zu erstellen und dann die Daten in die neue Tabelle zu übertragen.
Es gibt mehrere Möglichkeiten, dies zu tun, aber es gibt eine empfohlene Methode.
Der empfohlene Weg
Die SQLite-Dokumentation empfiehlt einen 12-Schritte-Prozess zum Vornehmen von Schemaänderungen an einer Tabelle.
Für die Zwecke dieses Artikels behandeln wir nur das Hinzufügen eines Fremdschlüssels.
Um es einigermaßen realistisch zu machen, stellen wir sicher, dass die Tabelle bereits Daten enthält.
Originaltabelle ohne Fremdschlüssel
Zuerst erstellen wir eine Tabelle ohne einen Fremdschlüssel und füllen Sie ihn mit Daten.
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 );
Eigentlich habe ich hier zwei Tabellen erstellt und mit Daten gefüllt. Zwei Tabellen, weil eine (Types ) hat den Primärschlüssel und den anderen (Haustiere ) wird den Fremdschlüssel haben.
Beachten Sie, dass ich keinen Fremdschlüssel erstellt habe.
Wir können überprüfen, ob keine Fremdschlüssel vorhanden sind, indem wir den folgenden Befehl ausführen:
PRAGMA foreign_key_list(Pets);
In meinem Fall erhalte ich folgendes Ergebnis:
(Das ist leer, weil es für diese Tabelle keine Fremdschlüsseleinschränkungen gibt.)
Lassen Sie uns nun einen Fremdschlüssel „hinzufügen“.
Fremdschlüssel hinzufügen
Der folgende Code fügt unserer Tabelle einen Fremdschlüssel hinzu, indem er eine neue Tabelle mit einer Fremdschlüsseleinschränkung erstellt, die Daten in diese Tabelle überträgt, die ursprüngliche Tabelle löscht und dann die neue Tabelle in den Namen der ursprünglichen Tabelle umbenennt.
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;
Fertig.
Wenn Sie Indizes, Trigger oder Ansichten rekonstruieren müssen, tun Sie dies nach ALTER TABLE
Anweisung, die die Tabelle umbenennt (kurz vor COMMIT
).
Lassen Sie uns nun die Tabelle erneut auf Fremdschlüsseleinschränkungen überprüfen.
.mode line
PRAGMA foreign_key_list(Pets);
Ergebnis (bei vertikaler Ausgabe):
id = 0 seq = 0 table = Types from = TypeId to = TypeId on_update = NO ACTION on_delete = NO ACTION match = NONE
Dieses Mal können wir die Details der Fremdschlüsseleinschränkung sehen.
Beachten Sie, dass die erste Zeile meines Befehls (.mode line
) hat nichts mit der Erstellung eines Fremdschlüssels zu tun. Ich habe es nur dort platziert, um die Art und Weise zu ändern, wie mein Terminal das Ergebnis ausgibt (damit Sie nicht seitwärts scrollen müssen, um das Ergebnis anzuzeigen).
Eine alternative Methode
Wenn Sie sich das vorherige Beispiel ansehen, denken Sie vielleicht, dass es einen effizienteren Weg gibt, dies zu tun. Sie könnten es zum Beispiel so machen:
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;
Und es ist wahr. Bei meinem Beispiel funktioniert diese Methode genauso gut.
Aber diese Methode hat auch das Potenzial, Verweise auf die Tabelle in allen vorhandenen Triggern, Ansichten und Fremdschlüsseleinschränkungen zu beschädigen.
Wenn Ihre Tabelle also bereits über vorhandene Auslöser, Ansichten oder Fremdschlüsseleinschränkungen verfügt, ist es wahrscheinlich sicherer, die empfohlene Methode zu verwenden.