Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Restrições de chave estrangeira:quando usar ON UPDATE e ON DELETE


Não hesite em colocar restrições no banco de dados. Você terá certeza de ter um banco de dados consistente, e esse é um dos bons motivos para usar um banco de dados. Especialmente se você tiver vários aplicativos solicitando (ou apenas um aplicativo, mas com um modo direto e um modo em lote usando fontes diferentes).

Com o MySQL você não tem restrições avançadas como teria no postgreSQL, mas pelo menos as restrições de chave estrangeira são bastante avançadas.

Vamos dar um exemplo, uma tabela de empresa com uma tabela de usuário contendo pessoas dessa empresa
CREATE TABLE COMPANY (
     company_id INT NOT NULL,
     company_name VARCHAR(50),
     PRIMARY KEY (company_id)
) ENGINE=INNODB;

CREATE TABLE USER (
     user_id INT, 
     user_name VARCHAR(50), 
     company_id INT,
     INDEX company_id_idx (company_id),
     FOREIGN KEY (company_id) REFERENCES COMPANY (company_id) ON...
) ENGINE=INNODB;

Vejamos a ATUALIZAÇÃO cláusula:
  • ATUALIZAÇÃO RESTRITA :o padrão :se você tentar atualizar um company_id na tabela COMPANY, o mecanismo rejeitará a operação se pelo menos um USER se vincular a essa empresa.
  • NA ATUALIZAÇÃO SEM AÇÃO :o mesmo que RESTRITO.
  • ATUALIZANDO CASCADE :o melhor geralmente :se você atualizar um company_id em uma linha da tabela COMPANY, o mecanismo irá atualizá-lo de acordo em todas as linhas USER referenciando esta COMPANY (mas nenhum gatilho ativado na tabela USER, aviso). O mecanismo rastreará as alterações para você, isso é bom.
  • ON UPDATE SET NULL :se você atualizar um company_id em uma linha da tabela COMPANY, o mecanismo definirá USERs relacionados company_id como NULL (deve estar disponível no campo USER company_id). Não vejo nada interessante para fazer com isso em uma atualização, mas posso estar errado.

E agora no ON DELETE lateral:
  • AO EXCLUIR RESTRITO :o padrão :se você tentar deletar um company_id Id na tabela COMPANY o motor irá rejeitar a operação se um USUÁRIO pelo menos linkar nesta empresa, pode salvar sua vida.
  • AO EXCLUIR SEM AÇÃO :o mesmo que RESTRITO
  • AO EXCLUIR CASCATA :perigoso :se você excluir uma linha de empresa na tabela EMPRESA, o mecanismo excluirá também os USUÁRIOS relacionados. Isso é perigoso, mas pode ser usado para fazer limpezas automáticas em tabelas secundárias (então pode ser algo que você deseja, mas certamente não para um exemplo de EMPRESA<->USUÁRIO)
  • ON DELETE SET NULL :punhado :se você excluir uma linha COMPANY, os USERs relacionados terão automaticamente o relacionamento com NULL. Se Nulo for seu valor para usuários sem empresa, isso pode ser um bom comportamento, por exemplo, talvez você precise manter os usuários em seu aplicativo, como autores de algum conteúdo, mas remover a empresa não é um problema para você.

geralmente meu padrão é:ON DELETE RESTRICT ON UPDATE CASCADE . com alguns ON DELETE CASCADE para tabelas de rastreamento (logs - não todos os logs -, coisas assim) e ON DELETE SET NULL quando a tabela mestre é um 'atributo simples' para a tabela que contém a chave estrangeira, como uma tabela JOB para a tabela USER.

Editar

Faz muito tempo que escrevi isso. Agora acho que devo acrescentar um aviso importante. O MySQL tem uma grande limitação documentada com cascatas. Cascatas não são acionadores . Portanto, se você estava confiante o suficiente nesse mecanismo para usar gatilhos, deve evitar restrições de cascata.

==> Veja abaixo a última edição, as coisas estão se movendo neste domínio

E eu não acho que isso vai ser consertado um dia. As restrições de chave estrangeira são gerenciadas pelo armazenamento InnoDb e os Triggers são gerenciados pelo mecanismo MySQL SQL. Ambos são separados. O Innodb é o único armazenamento com gerenciamento de restrições, talvez eles adicionem gatilhos diretamente no mecanismo de armazenamento um dia, talvez não.

Mas eu tenho minha própria opinião sobre qual elemento você deve escolher entre a implementação de gatilho ruim e o suporte de restrições de chaves estrangeiras muito úteis. E quando você se acostumar com a consistência do banco de dados, vai adorar o PostgreSQL.

12/2017-Atualizando esta edição sobre o MySQL:


como afirmado por @IstiaqueAhmed nos comentários, a situação mudou neste assunto. Então siga o link e confira a real situação atual (que pode mudar novamente no futuro).