Não hesite em colocar restrições no banco de dados. Você 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-o (ou apenas um aplicativo, mas com um modo direto e um modo em lote usando fontes diferentes).
Com o MySQL, você não possui restrições avançadas, como no postgreSQL, mas pelo menos as restrições de chave estrangeira são bastante avançadas.
Vamos dar um exemplo, uma tabela da empresa com uma tabela do 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;
Vamos dar uma olhada na cláusula ON UPDATE :
- ON UPDATE RESTRICT : o padrão : se você tentar atualizar um company_id na tabela COMPANY, o mecanismo rejeitará a operação se um USUÁRIO, pelo menos, vincular esta empresa.
- NA ATUALIZAÇÃO SEM AÇÃO : o mesmo que o RESTRITO.
- NO CASO DE ATUALIZAÇÃO : o melhor normalmente : se você atualizar um company_id em uma linha da tabela COMPANY, o mecanismo o atualizará de acordo com todas as linhas do USUÁRIO que fazem referência a essa EMPRESA (mas nenhum gatilho é ativado na tabela USER, aviso). O mecanismo acompanhará as alterações para você, é 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 consigo ver nada de interessante em uma atualização, mas posso estar errado.
E agora no lado ON DELETE :
- EM EXCLUIR RESTRITIVO : o padrão : se você tentar excluir um ID de company_id na tabela COMPANY, o mecanismo rejeitará a operação se um USUÁRIO, pelo menos, vincular esta empresa, poderá salvar sua vida.
- EM EXCLUIR SEM AÇÃO : o mesmo que RESTRITO
- EM EXCLUIR CASCADE : perigoso : se você excluir uma linha da 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 (portanto, pode ser algo que você deseja, mas certamente não para um exemplo de EMPRESA <-> USER)
- ON DELETE SET NULL : punhado : se você excluir uma linha da EMPRESA, os USUÁRIOS relacionados terão automaticamente o relacionamento com NULL. Se Nulo é o 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 o meu padrão é: ON DELETE RESTRICT ON UPDATE CASCADE . com algumas ON DELETE CASCADE
para tabelas de rastreamento (logs - nem todos os logs--, coisas assim) e ON DELETE SET NULL
quando a tabela principal é um 'atributo simples' para a tabela que contém a chave estrangeira, como uma tabela JOB para a tabela USER.
Editar
Faz muito tempo desde que escrevi isso. Agora acho que devo adicionar um aviso importante. O MySQL tem uma grande limitação documentada com cascatas. Cascatas não estão disparando gatilhos . Portanto, se você estava confiante o suficiente nesse mecanismo para usar gatilhos, deve evitar restrições em cascata.
Os gatilhos do MySQL são ativados apenas para alterações feitas nas tabelas por instruções SQL. Eles não são ativados para mudanças nas visualizações, nem nas tabelas feitas pelas APIs que não transmitem instruções SQL para o MySQL Server
==> Veja abaixo a última edição, as coisas estão mudando neste domínio
Os gatilhos não são ativados por ações de chave estrangeira.
E eu não acho que isso será corrigido um dia. As restrições de chave estrangeira são gerenciadas pelo armazenamento InnoDb e os Triggers são gerenciados pelo mecanismo SQL do MySQL. 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 tenho minha própria opinião sobre qual elemento você deve escolher entre a implementação deficiente do acionador e as 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 MySQL:
como afirma @IstiaqueAhmed nos comentários, a situação mudou neste assunto. Portanto, siga o link e verifique a situação real atualizada (que pode mudar novamente no futuro).
ON DELETE CASCADE : dangerous
- tome com uma pitada de sal.SET NULL
emON UPDATE
: atualizar uma empresa representa um desapego da relação Empresa> Usuário. Por exemplo: se uma empresa altera seu tipo de negócio, os usuários anteriores podem não estar mais relacionados a esse negócio, portanto,NULL
pode ser preferível para esse índice.This includes changes to base tables that underlie updatable views
vez do que você colou, ou seja,They do not activate for changes in views
CASCADE DELETE
geralmente também é aceitável, até preferida. Não considero isso particularmente perigoso.Além da resposta do @MarkR - uma coisa a ser observada seria que muitas estruturas PHP com ORMs não reconheceriam ou usariam a configuração avançada do banco de dados (chaves estrangeiras, exclusão em cascata, restrições exclusivas) e isso pode resultar em comportamento inesperado.
Por exemplo, se você excluir um registro usando ORM, e você
DELETE CASCADE
excluirá registros em tabelas relacionadas, a tentativa do ORM de excluir esses registros relacionados (geralmente automáticos) resultará em erro.fonte
Você precisará considerar isso no contexto do aplicativo. Em geral, você deve criar um aplicativo, não um banco de dados (o banco de dados simplesmente fazendo parte do aplicativo).
Considere como seu aplicativo deve responder a vários casos.
A ação padrão é restringir (ou seja, não permitir) a operação, que normalmente é o que você deseja, pois evita erros estúpidos de programação. No entanto, no DELETE CASCADE também pode ser útil. Realmente depende do seu aplicativo e de como você deseja excluir objetos específicos.
Pessoalmente, eu usaria o InnoDB porque ele não lixeira seus dados (cf MyISAM, o que faz), e não porque ele tem restrições de FK.
fonte