sql >> Base de Datos >  >> RDS >> SQLite

Agregar una clave externa a una tabla existente en SQLite

SQLite admite un subconjunto muy limitado de ALTER TABLE declaración. Lo único que puedes hacer con ALTER TABLE en SQLite es cambiar el nombre de una tabla, cambiar el nombre de una columna dentro de una tabla o agregar una nueva columna a una tabla existente.

En otras palabras, no puedes usar ALTER TABLE para agregar una clave externa a una tabla existente como puede hacerlo en otros sistemas de administración de bases de datos.

Por lo tanto, la única forma en que puede "agregar" una clave externa a una tabla existente en SQLite es crear una nueva tabla con una clave externa y luego transferir los datos a la nueva tabla.

Hay más de una forma de hacer esto, pero hay una forma recomendada.

La forma recomendada

La documentación de SQLite recomienda un proceso de 12 pasos para realizar cambios de esquema en una tabla.

A los efectos de este artículo, solo nos ocuparemos de agregar una clave externa.

Para que sea algo realista, nos aseguraremos de que la tabla ya contenga datos.

Tabla original sin clave externa

Primero, creemos una tabla sin una clave foránea y llénela con datos.

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 realidad, aquí creé dos tablas y las llené con datos. Dos tablas, porque una (Tipos ) tendrá la clave principal y la otra (Mascotas ) tendrá la clave externa.

Tenga en cuenta que no creé una clave externa.

Podemos comprobar que no existen claves foráneas ejecutando el siguiente comando:

PRAGMA foreign_key_list(Pets);

En mi caso, obtengo el siguiente resultado:

 

(Eso está en blanco porque no hay restricciones de clave externa en esta tabla).

Ahora vamos a "agregar" una clave externa.

Agregar clave externa

El siguiente código agrega una clave externa a nuestra tabla creando una nueva tabla con una restricción de clave externa, transfiriendo los datos a esa tabla, eliminando la tabla original y luego cambiando el nombre de la nueva tabla al nombre de la tabla original.

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;

Listo.

Si necesita reconstruir índices, disparadores o vistas, hágalo después de ALTER TABLE declaración que cambia el nombre de la tabla (justo antes de COMMIT ).

Ahora revisemos la tabla en busca de restricciones de clave externa nuevamente.

.mode line
PRAGMA foreign_key_list(Pets);

Resultado (usando salida vertical):

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

Esta vez podemos ver los detalles de la restricción de clave externa.

Tenga en cuenta que la primera línea de mi comando (.mode line ) no tiene nada que ver con la creación de una clave externa. Lo puse allí únicamente para cambiar la forma en que mi terminal muestra el resultado (para que no tenga que desplazarse hacia los lados para ver el resultado).

Un método alternativo

Al mirar el ejemplo anterior, podría estar pensando que hay una forma más eficiente de hacerlo. Por ejemplo, podrías hacerlo así:

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;

Y es verdad. Con mi ejemplo, este método funciona igual de bien.

Pero este método también tiene el potencial de corromper las referencias a la tabla en cualquier activador, vista y restricción de clave externa existente.

Entonces, si su tabla ya tiene activadores, vistas o restricciones de clave externa existentes, probablemente sea más seguro usar el método recomendado.