Ao configurar chaves estrangeiras no SQL Server, sob quais circunstâncias você deve fazê-lo em cascata ao excluir ou atualizar, e qual é o motivo por trás disso?
Isso provavelmente se aplica a outros bancos de dados também.
Estou procurando sobretudo exemplos concretos de cada cenário, de preferência de alguém que os tenha usado com sucesso.
sql-server
database-design
foreign-keys
rdbms
cascade
Joel Coehoorn
fonte
fonte
sql-server
tag.Respostas:
Resumo do que vi até agora:
Excluir em cascata
Atualização em cascata
Quando usar em cascata
fonte
Chaves estrangeiras são a melhor maneira de garantir a integridade referencial de um banco de dados. Evitar cascatas por ser mágico é como escrever tudo em montagem, porque você não confia na mágica por trás dos compiladores.
O que é ruim é o uso incorreto de chaves estrangeiras, como criá-las ao contrário, por exemplo.
O exemplo de Juan Manuel é o exemplo canônico, se você usar código, há muito mais chances de deixar DocumentItems espúrios no banco de dados que aparecerão e morderão você.
As atualizações em cascata são úteis, por exemplo, quando você tem referências aos dados por algo que pode mudar, digamos que uma chave primária de uma tabela de usuários seja o nome, a combinação de sobrenome. Então você deseja que as alterações nessa combinação sejam propagadas para onde quer que sejam referenciadas.
@Aidan, essa clareza a que você se refere tem um alto custo, a chance de deixar dados espúrios no seu banco de dados, o que não é pequeno . Para mim, geralmente é apenas a falta de familiaridade com o DB e a incapacidade de descobrir quais FKs existem antes de trabalhar com o DB que fomentam esse medo. Ou isso, ou uso indevido constante de cascata, usando-o onde as entidades não estavam conceitualmente relacionadas ou onde você precisa preservar a história.
fonte
Eu nunca uso exclusões em cascata.
Se eu quiser remover algo do banco de dados, quero explicitamente informar ao banco de dados o que quero remover.
É claro que elas são uma função disponível no banco de dados e pode haver momentos em que é bom usá-las, por exemplo, se você tiver uma tabela 'order' e uma tabela 'orderItem', poderá limpar os itens ao excluir um ordem.
Eu gosto da clareza que recebo ao fazê-lo no código (ou procedimento armazenado), em vez de acontecer 'mágica'.
Pela mesma razão, também não sou fã de gatilhos.
Algo a notar é que, se você excluir um 'pedido', receberá o relatório '1 linha afetada' de volta, mesmo que a exclusão em cascata tenha removido 50 'itens do pedido.
fonte
Eu trabalho muito com exclusões em cascata.
É bom saber quem trabalha com o banco de dados nunca pode deixar dados indesejados. Se as dependências crescem, apenas altero as restrições no diagrama no Management Studio e não preciso ajustar sp ou dados.
Dito isto, eu tenho um problema com exclusões em cascata e isso é referências circulares. Isso geralmente leva a partes do banco de dados que não têm exclusões em cascata.
fonte
Faço muito trabalho no banco de dados e raramente considero as exclusões em cascata úteis. A única vez em que os usei efetivamente está em um banco de dados de relatórios atualizado por um trabalho noturno. Asseguro que todos os dados alterados sejam importados corretamente, excluindo os registros de nível superior que foram alterados desde a última importação e, em seguida, reimporte os registros modificados e qualquer coisa relacionada a eles. Isso me salvou de ter que escrever muitas exclusões complicadas que aparecem da parte inferior à parte superior do meu banco de dados.
Eu não considero as exclusões em cascata tão ruins quanto os gatilhos, pois elas apenas excluem dados; eles podem ter todos os tipos de coisas desagradáveis.
Em geral, evito completamente exclusões reais e uso exclusões lógicas (ou seja, ter uma coluna de bits chamada isDeleted que seja configurada como true).
fonte
Um exemplo é quando você tem dependências entre entidades ... ou seja: Documento -> DocumentItems (quando você exclui Documento, DocumentItems não tem um motivo para existir)
fonte
Use a exclusão em cascata onde você deseja que o registro com o FK seja removido se o registro PK referente foi removido. Em outras palavras, onde o registro não faz sentido sem o registro de referência.
Acho a exclusão em cascata útil para garantir que as referências inativas sejam removidas por padrão, em vez de causar exceções nulas.
fonte
LIGAR Excluir cascata:
Quando você deseja que as linhas na tabela filho sejam excluídas Se a linha correspondente for excluída na tabela pai.
Se a exclusão em cascata não for usada, um erro será gerado para a integridade referencial .
Cascata de atualização ON:
Quando você deseja que a alteração na chave primária seja atualizada na chave estrangeira
fonte
Ouvi falar de DBAs e / ou "Política da Empresa" que proíbem o uso de "On Delete Cascade" (e outros) apenas por causa de más experiências no passado. Em um caso, um cara escreveu três gatilhos que acabaram se chamando. Três dias para recuperar resultaram em uma proibição total de gatilhos, tudo por causa das ações de um idjit.
É claro que às vezes são necessários gatilhos em vez de "Em exclusão em cascata", como quando alguns dados filhos precisam ser preservados. Mas em outros casos, é perfeitamente válido usar o método em cascata On Delete. Uma vantagem importante do "On Delete cascade" é que ele captura TODOS os filhos; um procedimento personalizado de ativação / armazenamento por escrito pode não funcionar se não estiver codificado corretamente.
Acredito que o desenvolvedor deve poder tomar a decisão com base no que é o desenvolvimento e no que as especificações dizem. Uma proibição de tapete baseada em uma experiência ruim não deve ser o critério; o processo de pensamento "Nunca use" é draconiano, na melhor das hipóteses. Uma chamada de julgamento precisa ser feita sempre e as alterações são feitas conforme o modelo de negócios muda.
Não é disso que se trata o desenvolvimento?
fonte
Um motivo para colocar uma exclusão em cascata (em vez de fazê-lo no código) é melhorar o desempenho.
Caso 1: com uma exclusão em cascata
Caso 2: sem exclusão em cascata
Em segundo lugar, quando você adiciona uma tabela filho extra com uma exclusão em cascata, o código no Caso 1 continua funcionando.
Eu colocaria apenas uma cascata em que a semântica do relacionamento é "parte de". Caso contrário, algum idiota excluirá metade do seu banco de dados quando você fizer:
fonte
Tento evitar exclusões ou atualizações que não solicitei explicitamente no SQL Server.
Em cascata ou pelo uso de gatilhos. Eles tendem a morder sua bunda por algum tempo, ao tentar rastrear um bug ou ao diagnosticar problemas de desempenho.
Onde eu os usaria é garantir consistência por pouco esforço. Para obter o mesmo efeito, você precisaria usar procedimentos armazenados.
fonte
Eu, como todo mundo aqui, acho que as exclusões em cascata são realmente apenas um pouco úteis (não é muito trabalhoso excluir dados referenciados em outras tabelas - se houver muitas tabelas, você simplesmente automatiza isso com um script), mas é realmente irritante quando alguém acidentalmente exclui em cascata alguns dados importantes que são difíceis de restaurar.
O único caso em que eu usaria é se os dados na tabela forem altamente controlados (por exemplo, permissões limitadas) e apenas atualizados ou excluídos de um processo controlado (como uma atualização de software) que foi verificado.
fonte
Uma exclusão ou atualização para S que remove um valor de chave estrangeira encontrado em algumas tuplas de R pode ser manipulada de uma de três maneiras:
A propagação é conhecida como cascata.
Existem dois casos:
‣ Se uma tupla em S foi excluída, exclua as tuplas R que se referem a ela.
‣ Se uma tupla em S foi atualizada, atualize o valor nas tuplas R que se referem a ela.
fonte
Se você estiver trabalhando em um sistema com muitos módulos diferentes em versões diferentes, pode ser muito útil se os itens excluídos em cascata fizerem parte / pertencem ao detentor do PK. Caso contrário, todos os módulos exigiriam correções imediatas para limpar seus itens dependentes antes de excluir o proprietário da PK, ou a relação de chave estrangeira seria completamente omitida, possivelmente deixando toneladas de lixo no sistema se a limpeza não for executada corretamente.
Acabei de introduzir a exclusão em cascata para uma nova tabela de interseção entre duas tabelas já existentes (a interseção para excluir apenas), depois que a exclusão em cascata foi desencorajada por algum tempo. Também não é tão ruim se os dados são perdidos.
No entanto, é uma coisa ruim nas tabelas de lista do tipo enum: alguém exclui a entrada 13 - amarela da tabela "cores" e todos os itens amarelos no banco de dados são excluídos. Além disso, eles às vezes são atualizados de uma maneira excluir tudo inserir, levando a integridade referencial totalmente omitida. É claro que está errado, mas como você mudará um software complexo que está em execução há muitos anos, com a introdução da verdadeira integridade referencial correndo o risco de efeitos colaterais inesperados?
Outro problema é quando os valores originais da chave estrangeira devem ser mantidos mesmo após a exclusão da chave primária. Pode-se criar uma coluna de marca para exclusão e uma opção ON DELETE SET NULL para o FK original, mas isso novamente requer gatilhos ou código específico para manter o valor da chave redundante (exceto após a exclusão da PK).
fonte
As exclusões em cascata são extremamente úteis ao implementar entidades lógicas de super-tipo e subtipo em um banco de dados físico.
Quando são usadas tabelas separadas de supertipo e subtipo para implementar fisicamente os supertipos / subtipos (em vez de acumular todos os atributos de subtipo em uma única tabela física de supertipo), existe uma tabela Um relacionamento entre essas tabelas e o problema passa a ser como manter as chaves primárias 100% sincronizadas entre essas tabelas.
As exclusões em cascata podem ser uma ferramenta muito útil para:
1) Verifique se a exclusão de um registro de supertipo também exclui o registro de subtipo único correspondente.
2) Verifique se qualquer exclusão de um subtipo de registro também exclui o registro de supertipo. Isso é alcançado implementando um gatilho de exclusão "em vez de" na tabela de subtipo que exclui o registro de supertipo correspondente, que, por sua vez, em cascata exclui o registro de subtipo.
O uso de exclusões em cascata dessa maneira garante que nunca existam registros de super-tipo ou subtipo órfãos, independentemente de você excluir primeiro o registro de super-tipo ou o primeiro subtipo.
fonte