sql >> Database >  >> RDS >> SQLite

Hoe een externe sleutel in SQLite te laten vallen

Als u een externe sleutel in SQL moet neerzetten, gebruikt u normaal gesproken de ALTER TABLE uitspraak. Maar als je SQLite gebruikt, is dat geen optie.

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 te laten vallen zoals je kunt in andere RDBMS'en

De aanbevolen manier om een ​​externe sleutel in SQLite te "laten vallen" is om de gegevens over te dragen naar een nieuwe tabel zonder een externe sleutel (of met een andere, als dat is wat u nodig hebt).

De aanbevolen manier

De SQLite-documentatie beveelt een proces van 12 stappen aan voor het aanbrengen van schemawijzigingen in een tabel. In het volgende voorbeeld gebruiken we dat proces om een ​​externe sleutel te "droppen".

Maak een tabel met een externe sleutel

Laten we eerst een tabel maken met de externe sleutel en deze vullen met gegevens.

CREATE TABLE Types( 
    TypeId INTEGER PRIMARY KEY, 
    Type
);

CREATE TABLE Pets( 
    PetId INTEGER PRIMARY KEY, 
    PetName,
    TypeId,
    FOREIGN KEY(TypeId) REFERENCES Types(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 de eerste (Typen ) heeft de primaire sleutel en de andere (Huisdieren ) heeft de externe sleutel. De externe sleutel is toegevoegd op de laatste regel van de tweede tabel.

We kunnen controleren of de externe sleutel is gemaakt door het volgende commando uit te voeren:

PRAGMA foreign_key_list(Pets);

Resultaat:

 id  seq  table  from    to      on_update  on_delete  match
 --  ---  -----  ------  ------  ---------  ---------  -----
 0   0    Types  TypeId  TypeId  NO ACTION  NO ACTION  NONE  

We kunnen de details van de externe sleutelbeperking zien.

Laten we nu de externe sleutel "laten vallen".

Laat de externe sleutel vallen

De volgende code "verwijdert" de refererende sleutel door een nieuwe tabel te maken zonder beperking van een refererende sleutel, de gegevens naar die tabel over te dragen, de originele tabel te verwijderen en de nieuwe tabel vervolgens te hernoemen naar de naam van de originele tabel.

PRAGMA foreign_keys = OFF;

BEGIN TRANSACTION;

CREATE TABLE Pets_new( 
    PetId INTEGER PRIMARY KEY, 
    PetName,
    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.

PRAGMA foreign_key_list(Pets);

Resultaat:

 

(Dat is blanco omdat er geen beperkingen zijn voor externe sleutels in deze tabel.)

U kunt dezelfde methode gebruiken om een ​​externe sleutel aan een bestaande tabel toe te voegen.

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
);

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. Waarom zijn Oracle-tabel-/kolom-/indexnamen beperkt tot 30 tekens?

  2. Hoe u de huidige weekgegevens in MySQL kunt krijgen

  3. Hoe verwijder ik alle niet-alfanumerieke tekens uit een string in MySQL?

  4. LEN-functie zonder volgspaties in SQL Server