SQLite
 sql >> Base de Dados >  >> RDS >> SQLite

Adicionar uma chave estrangeira a uma tabela existente no SQLite


SQLite suporta um subconjunto muito limitado do ALTER TABLE demonstração. As únicas coisas que você pode fazer com ALTER TABLE no SQLite é renomear uma tabela, renomear uma coluna dentro de uma tabela ou adicionar uma nova coluna a uma tabela existente.

Em outras palavras, você não pode usar ALTER TABLE para adicionar uma chave estrangeira a uma tabela existente, como em outros sistemas de gerenciamento de banco de dados.

Portanto, a única maneira de “adicionar” uma chave estrangeira a uma tabela existente no SQLite é criar uma nova tabela com uma chave estrangeira e depois transferir os dados para a nova tabela.

Há mais de uma maneira de fazer isso, mas há uma maneira recomendada.

A maneira recomendada


A documentação do SQLite recomenda um processo de 12 etapas para fazer alterações de esquema em uma tabela.

Para os propósitos deste artigo, trataremos apenas de adicionar uma chave estrangeira.

Para torná-lo um pouco realista, garantiremos que a tabela já contenha dados.

Tabela original sem chave estrangeira


Primeiro, vamos criar uma tabela sem uma chave estrangeira e preenchê-la com dados.
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 );

Na verdade, aqui eu criei duas tabelas e as preenchi com dados. Duas tabelas, porque uma (Tipos ) terá a chave primária e a outra (Animais de estimação ) terá a chave estrangeira.

Observe que eu não criei uma chave estrangeira.

Podemos verificar se não há chaves estrangeiras executando o seguinte comando:
PRAGMA foreign_key_list(Pets);

No meu caso, recebo o seguinte resultado:
 
(Isso está em branco porque não há restrições de chave estrangeira nesta tabela.)

Agora vamos “adicionar” uma chave estrangeira.

Adicionar chave estrangeira


O código a seguir adiciona uma chave estrangeira à nossa tabela criando uma nova tabela com uma restrição de chave estrangeira, transferindo os dados para essa tabela, descartando a tabela original e renomeando a nova tabela com o nome da tabela 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;

Feito.

Se você precisar reconstruir quaisquer índices, gatilhos ou visualizações, faça isso após o ALTER TABLE instrução que renomeia a tabela (logo antes de COMMIT ).

Agora vamos verificar a tabela para restrições de chave estrangeira novamente.
.mode line
PRAGMA foreign_key_list(Pets);

Resultado (usando saída vertical):
       id = 0
      seq = 0
    table = Types
     from = TypeId
       to = TypeId
on_update = NO ACTION
on_delete = NO ACTION
    match = NONE

Desta vez, podemos ver os detalhes da restrição de chave estrangeira.

Observe que a primeira linha do meu comando (.mode line ) não tem nada a ver com a criação de uma chave estrangeira. Eu o coloquei lá apenas para alterar a maneira como meu terminal gera o resultado (para que você não precise rolar para os lados para ver o resultado).

Um método alternativo


Ao olhar para o exemplo anterior, você pode estar pensando que existe uma maneira mais eficiente de fazer isso. Por exemplo, você poderia fazer assim:
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;

E é verdade. Com o meu exemplo, este método funciona tão bem.

Mas esse método também tem o potencial de corromper referências à tabela em quaisquer gatilhos, exibições e restrições de chave estrangeira existentes.

Portanto, se sua tabela já possui gatilhos, visualizações ou restrições de chave estrangeira, provavelmente é mais seguro usar o método recomendado.