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

Como descartar uma chave estrangeira no SQLite


Normalmente, se você precisar descartar uma chave estrangeira no SQL, você usaria o ALTER TABLE demonstração. Mas se você estiver usando SQLite, isso não é uma opção.

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 descartar uma chave estrangeira como você pode em outros RDBMSs

A maneira recomendada de “descartar” uma chave estrangeira no SQLite é, na verdade, transferir os dados para uma nova tabela sem uma chave estrangeira (ou com uma chave diferente, se for o que você precisa).

A maneira recomendada


A documentação do SQLite recomenda um processo de 12 etapas para fazer alterações de esquema em uma tabela. Usaremos esse processo para “descartar” uma chave estrangeira no exemplo a seguir.

Criar uma tabela com uma chave estrangeira


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

Na verdade, aqui eu criei duas tabelas e as preenchi com dados. Duas tabelas, porque a primeira (Tipos ) tem a chave primária e a outra (Animais de estimação ) tem a chave estrangeira. A chave estrangeira foi adicionada na última linha da segunda tabela.

Podemos verificar se a chave estrangeira foi criada executando o seguinte comando:
PRAGMA foreign_key_list(Pets);

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

Podemos ver os detalhes da restrição de chave estrangeira.

Agora vamos “descartar” a chave estrangeira.

"Solte" a chave estrangeira


O código a seguir “elimina” a chave estrangeira criando uma nova tabela sem 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
);

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.
PRAGMA foreign_key_list(Pets);

Resultado:
 
(Isso está em branco porque não há restrições de chave estrangeira nesta tabela.)

Você pode usar o mesmo método para adicionar uma chave estrangeira a uma tabela existente.

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

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.