SQLite
 sql >> Base de données >  >> RDS >> SQLite

Ajouter une clé étrangère à une table existante dans SQLite

SQLite prend en charge un sous-ensemble très limité de ALTER TABLE déclaration. Les seules choses que vous pouvez faire avec ALTER TABLE dans SQLite est de renommer une table, de renommer une colonne dans une table ou d'ajouter une nouvelle colonne à une table existante.

En d'autres termes, vous ne pouvez pas utiliser ALTER TABLE pour ajouter une clé étrangère à une table existante comme vous pouvez le faire dans d'autres systèmes de gestion de base de données.

Par conséquent, la seule façon d'"ajouter" une clé étrangère à une table existante dans SQLite est de créer une nouvelle table avec une clé étrangère, puis de transférer les données vers la nouvelle table.

Il existe plusieurs façons de procéder, mais il existe une méthode recommandée.

La méthode recommandée

La documentation SQLite recommande un processus en 12 étapes pour apporter des modifications de schéma à une table.

Pour les besoins de cet article, nous traiterons uniquement de l'ajout d'une clé étrangère.

Pour le rendre quelque peu réaliste, nous nous assurerons que le tableau contient déjà des données.

Table d'origine sans clé étrangère

Commençons par créer une table sans une clé étrangère et remplissez-la avec des données.

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

En fait, ici, j'ai créé deux tables et les ai remplies avec des données. Deux tables, car une (Types ) aura la clé primaire et l'autre (Pets ) aura la clé étrangère.

Notez que je n'ai pas créé de clé étrangère.

Nous pouvons vérifier qu'il n'y a pas de clés étrangères en exécutant la commande suivante :

PRAGMA foreign_key_list(Pets); 

Dans mon cas, j'obtiens le résultat suivant :

 

(Ceci est vide car il n'y a pas de contraintes de clé étrangère sur cette table.)

Maintenant, "ajoutons" une clé étrangère.

Ajouter une clé étrangère

Le code suivant ajoute une clé étrangère à notre table en créant une nouvelle table avec une contrainte de clé étrangère, en transférant les données vers cette table, en supprimant la table d'origine, puis en renommant la nouvelle table avec le nom de la table d'origine.

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; 

Terminé.

Si vous avez besoin de reconstruire des index, des déclencheurs ou des vues, faites-le après ALTER TABLE instruction qui renomme la table (juste avant COMMIT ).

Maintenant, vérifions à nouveau la table pour les contraintes de clé étrangère.

.mode line
PRAGMA foreign_key_list(Pets); 

Résultat (en utilisant la sortie verticale) :

 id =0 seq =0 table =Types from =TypeId to =TypeIdon_update =NO ACTIONon_delete =NO ACTION match =NONE

Cette fois, nous pouvons voir les détails de la contrainte de clé étrangère.

Notez que la première ligne de ma commande (.mode line ) n'a rien à voir avec la création d'une clé étrangère. Je l'ai mis là uniquement pour changer la façon dont mon terminal affiche le résultat (afin que vous n'ayez pas à faire défiler latéralement pour voir le résultat).

Une méthode alternative

En regardant l'exemple précédent, vous pensez peut-être qu'il existe un moyen plus efficace de le faire. Par exemple, vous pourriez le faire comme ceci :

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; 

Et c'est vrai. Avec mon exemple, cette méthode fonctionne tout aussi bien.

Mais cette méthode a également le potentiel de corrompre les références à la table dans tous les déclencheurs, vues et contraintes de clé étrangère existants.

Ainsi, si votre table possède déjà des déclencheurs, des vues ou des contraintes de clé étrangère, il est probablement plus sûr d'utiliser la méthode recommandée.