SQLite
 sql >> Database >  >> RDS >> SQLite

Come eliminare una chiave esterna in SQLite

Normalmente se devi eliminare una chiave esterna in SQL, utilizzeresti ALTER TABLE dichiarazione. Ma se stai usando SQLite, questa non è un'opzione.

SQLite supporta un sottoinsieme molto limitato di ALTER TABLE dichiarazione. Le uniche cose che puoi fare con ALTER TABLE in SQLite è rinominare una tabella, rinominare una colonna all'interno di una tabella o aggiungere una nuova colonna a una tabella esistente.

In altre parole, non puoi usare ALTER TABLE per rilasciare una chiave esterna come puoi fare in altri RDBMS

Il modo consigliato per "eliminare" una chiave esterna in SQLite è in realtà trasferire i dati in una nuova tabella senza una chiave esterna (o con una diversa, se è quello che ti serve).

Il modo consigliato

La documentazione di SQLite consiglia un processo in 12 fasi per apportare modifiche allo schema a una tabella. Utilizzeremo questo processo per "eliminare" una chiave esterna nell'esempio seguente.

Crea una tabella con una chiave esterna

Per prima cosa, creiamo una tabella con la chiave esterna e la popolamo con i dati.

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

In realtà, qui ho creato due tabelle e le ho popolate con i dati. Due tabelle, perché la prima (Tipi ) ha la chiave primaria e l'altra (Animali domestici ) ha la chiave esterna. La chiave esterna è stata aggiunta nell'ultima riga della seconda tabella.

Possiamo verificare che la chiave esterna sia stata creata eseguendo il seguente comando:

PRAGMA foreign_key_list(Pets);

Risultato:

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

Possiamo vedere i dettagli del vincolo di chiave esterna.

Ora "rilasciamo" la chiave esterna.

"Elimina" la chiave esterna

Il codice seguente "elimina" la chiave esterna creando una nuova tabella senza un vincolo di chiave esterna, trasferendo i dati a quella tabella, eliminando la tabella originale, quindi rinominando la nuova tabella con il nome della tabella originale.

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;

Fatto.

Se hai bisogno di ricostruire indici, trigger o viste, fallo dopo ALTER TABLE istruzione che rinomina la tabella (appena prima di COMMIT ).

Ora controlliamo di nuovo la tabella per i vincoli di chiave esterna.

PRAGMA foreign_key_list(Pets);

Risultato:

 

(Questo è vuoto perché non ci sono vincoli di chiave esterna su questa tabella.)

Puoi utilizzare lo stesso metodo per aggiungere una chiave esterna a una tabella esistente.

Un metodo alternativo

Osservando l'esempio precedente, potresti pensare che esiste un modo più efficiente per farlo. Ad esempio potresti farlo in questo modo:

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;

Ed è vero. Con il mio esempio, questo metodo funziona altrettanto bene.

Ma questo metodo ha anche il potenziale per corrompere i riferimenti alla tabella in qualsiasi trigger, vista e vincolo di chiave esterna esistenti.

Quindi, se la tua tabella ha già trigger, viste o vincoli di chiave esterna esistenti, è probabilmente più sicuro utilizzare il metodo consigliato.