sql >> Database >  >> RDS >> SQLite

Een externe sleutel toevoegen aan een bestaande tabel in SQLite

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.


  1. Grondbeginselen van tabeluitdrukkingen, deel 12 - Inline tabelwaardige functies

  2. Java-kruistabel - query voor opgestelde instructie

  3. Typ conversie. Wat moet ik doen met een PostgreSQL OID-waarde in libpq in C?

  4. Een web-app maken vanaf nul met Python Flask en MySQL:deel 2