Pergunta

Quando a configuração de chaves estrangeiras no SQL Server, em que circunstâncias você deve tê-lo em cascata em delete ou update, e o que é o raciocínio por trás disso?

Provavelmente, isso se aplica a outras bases de dados.

Estou procurando por exemplos concretos de cada cenário, de preferência de alguém que já tenha usado com sucesso.

Foi útil?

Solução

Resumo do que eu vi até agora:

  • Algumas pessoas não gostam de cascata em todos os.

Exclusão Em Cascata

  • Exclusão em cascata pode fazer sentido quando a semântica do relacionamento pode envolver um exclusivo "é parte da"a descrição.Por exemplo, um OrderLine registo é parte de seu pai da ordem, e OrderLines nunca vai ser compartilhado entre várias ordens.Se a Ordem fosse a desaparecer, o OrderLine, bem como, e de uma linha sem uma Ordem seria um problema.
  • O exemplo canônico para exclusão em Cascata é SomeObject e SomeObjectItems, onde não faz qualquer sentido para um itens de registro de existir sem o correspondente registro principal.
  • Você deve não usar Cascade Delete se você é preservar a história ou a utilização de um "soft/lógica da exclusão", onde você apenas definir um excluído coluna de bit para 1/true.

Atualização Em Cascata

  • Atualização em cascata pode fazer sentido quando você usar a chave real em vez de uma chave substituta (de identidade/coluna autoincrement) através de tabelas.
  • O exemplo canônico para a Atualização em Cascata é quando você tem um mutável de chave estrangeira, como um nome de usuário que pode ser alterado.
  • Você deve não utilização de Atualização em Cascata com chaves de Identidade/autoincrement colunas.
  • Atualização em cascata é melhor usado em conjunto com uma restrição exclusiva.

Quando Usar Em Cascata

  • Você pode querer obter um extra forte confirmação da volta do usuário antes de permitir que uma operação em cascata, mas isso depende de sua aplicação.
  • Cascata pode causar problemas se você configurar suas chaves estrangeiras errado.Mas você deve estar bem se você fizer isso direito.
  • Não é sábio usar em cascata antes de compreendê-lo completamente.No entanto, é um recurso útil e, portanto, vale a pena tomar o tempo para compreender.

Outras dicas

Chaves estrangeiras são a melhor maneira de garantir a integridade referencial do banco de dados.Evitando cascatas devido a ser a magia é como escrever tudo em assembléia, porque você não confia a magia por trás de compiladores.

O que é ruim, é errado o uso de chaves estrangeiras, como criá-los para trás, por exemplo.

Juan Manuel exemplo é o exemplo canônico, se você usar o código há muito mais chances de deixar espúrias DocumentItems no banco de dados que virá e morder você.

Atualizações em cascata são úteis, por exemplo, quando você tem referências a dados por algo que pode mudar, por exemplo, uma chave primária de uma tabela de usuários é o nome,sobrenome combinação.Então você quer mudanças em que a combinação de propagar para onde são referenciados.

@Aidan, Que a clareza que você consulte vem a um custo alto, a chance de deixar espúria de dados em seu banco de dados, que é não é pequeno o.Para mim, é geralmente apenas uma falta de familiaridade com o DB e a incapacidade de encontrar o que FKs estão no lugar antes de trabalhar com o DB que fomentam o medo.Ou isso, ou o constante uso indevido de cascata, utilizando, onde as entidades não foram conceitualmente relacionados, ou onde você tem que preservar a história.

Eu nunca uso exclusões em cascata.

Se eu quero algo removido do banco de dados que eu quero dizer explicitamente o banco de dados que eu quero tirar.

É claro que eles são uma função disponível no banco de dados e pode haver momentos em que é bom usá-los, por exemplo, se você tem uma 'ordem' e 'orderItem' tabela você pode querer desmarcar os itens quando você excluir um fim.

Eu gosto da clareza que eu tenho de fazê-lo no código (ou procedimento armazenado) em vez de 'magia' acontecendo.

Pela mesma razão, eu não sou um fã do provocam.

Algo a notar é que, se você excluir uma 'ordem' você vai ficar '1 linha afetada' relatório de volta, mesmo se a excluir em cascata foi removido 50 'orderItem s.

Eu trabalho muito com eliminações em cascata.

É bom saber quem trabalha contra o banco de dados pode nunca deixar de quaisquer dados indesejados.Se dependências crescer eu só alterar as restrições no diagramm no Management Studio e eu não tenho que ajustar sp ou dataacces.

Dito isso, eu tenho 1 problema com eliminações em cascata e é para isso referências circulares.Isso muitas vezes leva a partes do banco de dados que não possuem exclusões em cascata.

Eu faço um monte de trabalho de banco de dados e raramente encontrar eliminações em cascata útil.O tempo que eu tenho usado com eficácia em um relatório de banco de dados que é atualizada por uma tarefa noturna.I certifique-se de que quaisquer dados alterados são importados corretamente, excluindo qualquer nível superior registros que foram alterados desde a última importação, em seguida, importar os registos modificados e tudo o que se relaciona com eles.Ele me poupar de ter que escrever muito complicado exclui que olhar a partir da parte inferior para a parte superior de meu banco de dados.

Eu não considera eliminações em cascata para ser tão ruim como gatilhos, como eles só excluir dados, triggers podem ter todos os tipos de coisas desagradáveis dentro.

Em geral, eu evitar real Exclui totalmente e usar lógica exclui (ie.ter uma coluna de bit chamado isDeleted que é definido como verdadeiro) em vez disso.

Um exemplo é quando você tem dependências entre entidades da...ou seja:Documento -> DocumentItems (quando você excluir Documento, DocumentItems não tem uma razão para existir)

Usar cascade delete onde você deseja que o registro com o FK para ser removido se a sua referência PK registro foi removido.Em outras palavras, onde o registro é sentido sem a referência de registo.

Eu acho exclusão em cascata útil para garantir que o morto referências são removidos por padrão ao invés de causar nulo exceções.

ON Delete Cascade:

Quando você quiser linhas na tabela filho para ser eliminado Se linha correspondente é eliminado na tabela pai.

Se em cascade delete não é utilizado, então, um erro será gerado para a integridade referencial.

ON Update Cascade:

Quando você quiser alteração na chave primária a ser atualizada na chave estrangeira

Uma razão para colocar em uma exclusão em cascata (ao invés de fazê-lo no código) é para melhorar o desempenho.

Caso 1:Com uma exclusão em cascata

 DELETE FROM table WHERE SomeDate < 7 years ago;

Caso 2:Sem uma exclusão em cascata

 FOR EACH R IN (SELECT FROM table WHERE SomeDate < 7 years ago) LOOP
   DELETE FROM ChildTable WHERE tableId = R.tableId;
   DELETE FROM table WHERE tableId = R.tableid;
   /* More child tables here */
 NEXT

Em segundo lugar, quando você adicionar um extra de criança mesa com uma cascata de eliminar, o código de Caso 1 continua trabalhando.

Gostaria apenas de colocar em uma cascata, onde a semântica do relacionamento é "parte de".Caso contrário, algum idiota vai eliminar metade de seu banco de dados quando você fizer:

DELETE FROM CURRENCY WHERE CurrencyCode = 'USD'

Tenho ouvido falar de DBAs e/ou "Sociedade Política" que proíbem o uso de "On Delete Cascade" (e outros) puramente por causa de más experiências no passado.Em um caso, um cara escreveu três gatilhos que acabou chamando um ao outro.Três dias para se recuperar resultou em uma proibição total de gatilhos, tudo por causa das ações de uma idjit.

É claro que Dispara, algumas vezes, são necessárias, em vez de "On Delete cascade", como quando uma criança de dados precisa ser preservado.Mas, em outros casos, perfeitamente válida para usar o On Delete cascade método.Uma vantagem chave de "On Delete cascade" é que ele captura TODAS as crianças;um personalizado escrito gatilho/loja procedimento não podem se ele não está codificado corretamente.

Eu acredito que o Desenvolvedor deveria ser autorizado a tomar a decisão com base no que o desenvolvimento é e o que a especificação diz.Um tapete de proibição com base em uma experiência ruim não deve ser o critério;o "Nunca use" processo de pensamento é draconiana, na melhor das hipóteses.Um julgamento deve ser feito a cada momento, e as alterações feitas, como o modelo de negócio e mudanças.

Não foi isso que o desenvolvimento é tudo sobre?

Eu tento evitar exclui ou atualizações que eu não explicitamente pedido no SQL server.

Através de cascata ou através da utilização de gatilhos.Eles tendem a mordê-lo na bunda de algum tempo para baixo da linha, ao tentar rastrear um erro ou quando o diagnóstico de problemas de desempenho.

Onde eu iria usá-los para garantir a consistência não muito esforço.Para obter o mesmo efeito, você teria de usar procedimentos armazenados.

Eu, como todo mundo aqui, achar que eliminações em cascata são realmente apenas marginalmente úteis (não é realmente muito trabalho para apagar os dados referenciados em outras tabelas -- se houver muitas tabelas, você simplesmente automatizar esta com um script), mas realmente irritante quando alguém acidentalmente eliminações em cascata alguns dados importantes que é difícil restaurar.

O único caso em que eu uso é se os dados da tabela a tabela é altamente controlado (por exemplo, permissões limitadas) e apenas actualizados ou eliminados através de um processo controlado (como uma atualização de software), que tem sido verificada.

Uma exclusão ou atualização que remove uma chave estrangeira valor encontrado em algumas tuplas de R pode ser realizada de três maneiras:

  1. Rejeição
  2. Propagação
  3. anulação.

A propagação é referido como em cascata.

Existem dois casos:

‣ Se uma tupla no S foi eliminado, eliminar as tuplas de R que se refere a ele.

‣ Se uma tupla no S foi atualizado, atualize o valor em R tuplas que se referem a isso.

Se você estiver trabalhando em um sistema com vários módulos diferentes em diferentes versões, pode ser muito útil, se a cascata de itens excluídos são parte de / propriedade do PK titular.Outra coisa, todos os módulos exigiria imediata patches para limpar seus dependentes itens antes de excluir o PK proprietário, ou o de chave estrangeira relação seria completamente omitida, possivelmente deixando de toneladas de lixo no sistema se a limpeza não é executada corretamente.

Eu só introduziu exclusão em cascata para um novo cruzamento de mesa entre duas já existentes tabelas (interseção para excluir apenas), após a exclusão em cascata havia sido desencorajado por algum tempo.Também não é muito ruim, se os dados se perdem.

É, no entanto, uma coisa ruim no enum lista de tabelas:alguém elimina uma entrada 13 - amarelo da tabela de "cores", e todos os itens amarelos na base de dados excluídos.Além disso, estes, por vezes, ficar atualizada em excluir tudo-inserir todos os tipos, levando a integridade referencial totalmente omitida.É claro que é errado, mas como você vai mudar de um software complexo que tem sido executado por muitos anos, com a introdução da verdadeira integridade referencial em risco de efeitos colaterais inesperados?

Outro problema é quando o original de valores de chave externa deve ser mantido mesmo depois que a chave primária foi eliminado.Pode-se criar uma marca para exclusão de coluna e um ON DELETE SET NULL opção para o original FK, mas novamente, isso requer disparadores ou de um código específico para manter a redundantes (exceto após o PK de exclusão) valor da chave.

Exclusões em cascata são extremamente úteis ao implementar a lógica de super-tipo e sub-tipo de entidades em um banco de dados físico.

Quando separados super-tipo e sub-tipo de tabelas são usadas para implementar fisicamente super-tipos/sub-tipos (como oposição à realização de backup de todos os sub-atributos de tipo em um único super-tipo de tabela), há uma relação um-para-um relacionamento entre essas tabelas e o problema torna-se então como manter as chaves primárias de 100% em sincronia entre essas tabelas.

Exclusões em cascata pode ser uma ferramenta muito útil para:

1) certifique-se de que a exclusão de um super-tipo de registro também exclui a única correspondente sub-tipo de registro.

2) certifique-se de que qualquer eliminação de um sub-registro de tipo exclui o super-tipo de registro.Isto é conseguido através da implementação de um "em vez de" disparador de exclusão na sub-tipo de tabela que vai e apaga o correspondente super-tipo de registro, o que, por sua vez, eliminações em cascata o sub-tipo de registro.

Usando eliminações em cascata desta forma garante que nenhum órfão super-tipo ou subtipo de registros já existentes, independentemente de se você excluir o super-tipo de registo de primeiro ou o sub-tipo de registro primeiro.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top