SQLite stöder en mycket begränsad delmängd av ALTER TABLE
påstående. Det enda du kan göra med ALTER TABLE
i SQLite byter man namn på en tabell, byter namn på en kolumn i en tabell eller lägger till en ny kolumn i en befintlig tabell.
Med andra ord kan du inte använda ALTER TABLE
att lägga till en främmande nyckel till en befintlig tabell som du kan i andra databashanteringssystem.
Därför är det enda sättet du kan "lägga till" en främmande nyckel till en befintlig tabell i SQLite att skapa en ny tabell med en främmande nyckel och sedan överföra data till den nya tabellen.
Det finns mer än ett sätt att göra detta, men det finns ett rekommenderat sätt.
Det rekommenderade sättet
SQLite-dokumentationen rekommenderar en 12-stegsprocess för att göra schemaändringar i en tabell.
I den här artikeln kommer vi bara att ta itu med att lägga till en främmande nyckel.
För att göra det lite realistiskt ser vi till att tabellen redan innehåller data.
Original tabell utan främmande nyckel
Låt oss först skapa en tabell utan en främmande nyckel och fyll 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 );
Här skapade jag faktiskt två tabeller och fyllde i dem med data. Två tabeller, eftersom en (Typer ) kommer att ha den primära nyckeln och den andra (Husdjur ) kommer att ha den främmande nyckeln.
Lägg märke till att jag inte skapade en främmande nyckel.
Vi kan verifiera att det inte finns några främmande nycklar genom att köra följande kommando:
PRAGMA foreign_key_list(Pets);
I mitt fall får jag följande resultat:
(Det är tomt eftersom det inte finns några begränsningar för främmande nyckel i den här tabellen.)
Låt oss nu "lägga till" en främmande nyckel.
Lägg till främmande nyckel
Följande kod lägger till en främmande nyckel till vår tabell genom att skapa en ny tabell med en främmande nyckel-begränsning, överföra data till den tabellen, släppa den ursprungliga tabellen och sedan byta namn på den nya tabellen till namnet på den ursprungliga tabellen.
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;
Klart.
Om du behöver rekonstruera några index, utlösare eller vyer, gör det efter ALTER TABLE
uttalande som byter namn på tabellen (strax före COMMIT
).
Låt oss nu kontrollera tabellen för främmande nyckelbegränsningar igen.
.mode line
PRAGMA foreign_key_list(Pets);
Resultat (med vertikal utdata):
id = 0 seq = 0 table = Types from = TypeId to = TypeId on_update = NO ACTION on_delete = NO ACTION match = NONE
Den här gången kan vi se detaljerna om den främmande nyckeln.
Observera att den första raden i mitt kommando (.mode line
) har inget att göra med att skapa en främmande nyckel. Jag har lagt det där enbart för att ändra hur min terminal matar ut resultatet (så att du inte behöver rulla i sidled för att se resultatet).
En alternativ metod
När du tittar på det föregående exemplet kanske du tänker att det finns ett mer effektivt sätt att göra det. Du kan till exempel göra så här:
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;
Och det är sant. Med mitt exempel fungerar den här metoden lika bra.
Men den här metoden har också potential att korrumpera referenser till tabellen i alla befintliga triggers, vyer och främmande nyckelbegränsningar.
Så om din tabell redan har befintliga utlösare, vyer eller begränsningar för främmande nyckel, är det förmodligen säkrare att använda den rekommenderade metoden.