2
respostas

A única opção válida é a D, que utiliza um 'Alter Table', mas no contexto do SQLite esta opção é uma prática recomendada?

Veja o que a Luri menciona:
No contexto do SQLite, a sintaxe ALTER TABLE ... ADD COLUMN ... REFERENCES é válida e funciona para adicionar uma coluna que é uma chave estrangeira.
No entanto, a prática mais comum e recomendada para adicionar uma chave estrangeira a uma tabela existente no SQLite, especialmente se você quiser que ela seja uma restrição de chave estrangeira (que o SQLite vai validar), é um pouco diferente da que foi apresentada na resposta.

A sintaxe que você viu adiciona a coluna e a referência, mas o SQLite tem algumas limitações com ALTER TABLE para adicionar restrições de chave estrangeira diretamente a colunas existentes ou para adicionar novas colunas com restrições de chave estrangeira que apontam para tabelas que ainda não existem ou que não foram configuradas para aceitar chaves estrangeiras.

Para o SQLite, a forma mais robusta de adicionar uma chave estrangeira a uma tabela existente, garantindo que a restrição seja aplicada e validada, geralmente envolve:

  • Criar uma nova tabela com a estrutura desejada, incluindo a chave estrangeira.
  • Copiar os dados da tabela antiga para a nova.
  • Excluir a tabela antiga.
  • Renomear a nova tabela para o nome da tabela antiga.

Isso é um processo mais complexo, mas garante que todas as restrições, incluindo as de chave estrangeira, sejam aplicadas corretamente desde o início.

2 respostas

Oi Marcos, tudo bem?

Sim, existe uma limitação ao usar ALTER TABLE em conjunto com FOREIGN KEY em tabelas já existentes, principalmente quando a estrutura atual não foi criada considerando essa relação desde o início.

No contexto dessa atividade, o objetivo é apenas adicionar a chave estrangeira na tabela de produtos. Para isso, você pode utilizar o ALTER TABLE para incluir a coluna já com a restrição de chave estrangeira.

Caso a coluna de fornecedor já exista, uma abordagem comum é removê-la e criá-la, agora vinculada à tabela de fornecedores, conforme proposto na alternativa d.

Outra alternativa é criar uma nova tabela já com os relacionamentos definidos corretamente e, em seguida, migrar os dados da tabela antiga para essa nova estrutura, removendo a tabela anterior depois disso. Como a IA sugeriu.

Assim, você garante a integridade dos dados e evita conflitos com restrições já existentes.

Abaixo, deixo um tópico relacionado a essa dúvida. Recomendo fortemente que você faça a leitura deste e também dos outros linkados nele, pois podem complementar seu entendimento sobre o tema.

Espero ter ajudado.

Qualquer dúvida que surgir, compartilhe no fórum. Abraços e bons estudos!

Caso este post tenha lhe ajudado, por favor, marcar como solucionado ✓. Bons Estudos!

Boa tarde, Monalisa. Obrigado pelo retorno.

Me parece que o relacionamento correto é pela coluna já existente fornecedor, e não criando uma segunda coluna fk_fornecedor. Em SQLite, a forma adequada é definir a chave estrangeira na própria CREATE TABLE, por exemplo:

CREATE TABLE fornecedores (
    id INTEGER PRIMARY KEY
);

CREATE TABLE produtos (
    id INTEGER PRIMARY KEY,
    nome VARCHAR(255),
    descricao TEXT,
    categoria INT,
    preco DECIMAL(10, 2),
    unidade VARCHAR(50),
    fornecedor INTEGER,
    data_inclusao DATE,
    FOREIGN KEY (fornecedor) REFERENCES fornecedores(id)
);

O SQLite também aceita a forma “inline”, como fornecedor INTEGER REFERENCES fornecedores(id). As duas representam a FK; a condição importante é que a coluna referenciada na tabela-pai seja PRIMARY KEY ou esteja sob UNIQUE. (https://sqlite.org/foreignkeys.html)

O comando da opção D, não me parece a correção adequada, porque cria uma nova coluna chamada fk_fornecedor, ao invés de transformar a coluna atual fornecedor em chave estrangeira. Então a tabela acaba com duas colunas (fornecedor e fk_fornecedor), e a original continua sem restrição referencial.

Além disto, em SQLite, quando foreign_keys está habilitado, um ADD COLUMN com REFERENCES só é permitido se a nova coluna tiver DEFAULT NULL. Mesmo quando o comando é aceito, ele resolve outro problema: acrescentar uma coluna nova, não corrigir a modelagem já existente. (https://www.sqlite.org/lang_altertable.html)

O procedimento mais adequado que encontrei é:

  1. Verificar se há dados órfãos em produtos.fornecedor antes da migração.
  2. Se as FKs estiverem habilitadas, desligá-las fora da transação.
  3. Criar uma nova tabela produtos_novo com a FK correta.
  4. Copiar os dados da tabela antiga para a nova.
  5. Excluir a tabela antiga.
  6. Renomear produtos_novo para produtos.
  7. Recriar índices, triggers e views, se existirem.
  8. Rodar PRAGMA foreign_key_check.
  9. Fazer COMMIT.
  10. Reabilitar PRAGMA foreign_keys = ON.

Este é o fluxo seguro recomendado pelo SQLite para alterações de schema que não cabem no ALTER TABLE simples.(https://www.sqlite.org/lang_altertable.html)

Cordialmente,
Marcos.