Registros "excluídos" em cascata que não são realmente excluídos

8

Apenas tentando ter algumas idéias sobre o que as pessoas fazem para esse cenário. Temos um banco de dados do sistema (SQL Server 2008 R2) que possui tabelas e cada tabela possui um campo que podemos chamar de "Excluídos". Basicamente, é um campo de bits se for um 1 o registro for excluído, se for um 0, não será excluído. O campo não é anulável e seu padrão é obviamente 0.

Não podemos permitir exclusões reais no banco de dados; portanto, para contornar isso, definimos um campo de bit (Excluído) como true. Em nossa aplicação, terminamos com consultas parecidas com esta:

SELECT blah FROM MyTable WHERE .. AND Deleted=0

Basicamente, filtramos os registros para obter apenas linhas não excluídas. Nosso problema está nos registros relacionados que precisam ser conectados em cascata. O que as pessoas preferem, deveríamos fazer isso no código do servidor para que, quando você exclua um registro, ele exclua (Define o campo de bit excluído como true) para todos os registros relacionados? Ou isso deve ser um gatilho que deve verificar esse campo e definir o campo de bit para todos os registros relacionados como 1?

Ou estamos completamente no caminho errado?

JonH
fonte
usar uma exibição tão excluída nunca chegar para a foto, eo grupo em que bitfield
aberração catraca
@ratchetfreak - isso não ajuda nos registros relacionados ... como você lida com a cascata da exclusão. Imagine uma página da empresa que tenha problemas associados, se alguém excluir a empresa (define Company.Deleted = 1) como você exclui os problemas associados a essa empresa?
Jonh
2
única coisa que poderia automatizar é uma atualização gatilho
aberração catraca
1
@ratchetfreak - Esse é o tipo da minha pergunta, devemos lidar com isso por meio de um gatilho de atualização ou pelo código do servidor, e por quê. Eu meio que sei a resposta para isso. Eu estava apenas esperando ter uma idéia do que os outros fazem para a exclusão virtual - como você excluiria os relacionamentos (a exclusão em cascata tem você sem realmente excluir).
Jonh
2
Por que você precisa excluir dados relacionados? Se o pai dos dados relacionados estiver inacessível, como você os acessará?
Kevin Kevin

Respostas:

2

Não há boa solução aqui. Os bancos de dados oferecem exclusão em cascata eficiente e especial por meio de chaves estrangeiras, mas se, como você diz, a exclusão real não for uma opção, não será possível tirar proveito dessa cascata nativa.

Dependendo se as exclusões são comuns ou raras, será mais eficiente emular a cascata imediatamente (por meio de consultas ou gatilhos extras) quando você pseudo-excluir algo, ou apenas para sempre buscar tudo no banco de dados e filtrar a exclusão sinalizador na lógica de negócios.

Pessoalmente, sempre usei uma terceira opção: todos os registros subsidiários são acessíveis apenas a partir do registro mestre, o que nunca acontece se esse for excluído com suavidade; portanto, você não precisa fazer nada! Obviamente, isso só funciona se o seu modelo de dados for uma árvore estrita (os comentários são recuperados apenas ao visualizar o produto ao qual se aplicam, os privilégios do usuário são recuperados apenas ao administrar o usuário ao qual pertencem etc.) em vez de uma Web (onde você pode consultar todos os comentários ou todos os registros de privilégios com indiferença), mas acho que isso pode funcionar para surpreendentemente muitos cenários.

Kilian Foth
fonte
@Killian - Eu acredito que este pode ser o caminho que devemos seguir (gatilhos). No entanto, como equipe, precisamos discutir isso mais com os interessados ​​sobre o que deve ou não cascatear. Obrigado pela sua contribuição impressionante.
Jonh
5

Já fiz isso antes com tabelas de auditoria, nas quais todas as alterações em um banco de dados são gravadas em uma tabela de espelho de auditoria (Inserir / Atualizar / Excluir) e os itens reais reais são excluídos de maneira cascata.

As tabelas de espelhamento são idênticas à tabela real com a adição de 3 colunas, "ChangeType", "Usuário", "Data".

Isso tem a dupla vantagem de poder excluir dados corretamente, mas também permitir que o estado do banco de dados seja recriado a qualquer momento e que o histórico completo de qualquer item seja documentado.

Acrescentarei que, para exclusões em cascata, geralmente prefiro exclusões em cascata no cliente - o servidor não deve tentar ser muito inteligente quanto a isso, se um usuário excluir uma empresa e que tiver problemas associados - a ação excluir empresa também deve excluir quaisquer registros correspondentes.

Isso era para um sistema de gestão financeira de um grande banco de investimento, portanto a auditabilidade era uma característica crítica.

Michael
fonte
Eu posso ver isso de uma maneira e pensamos nisso, mas acredito que se encaixa nos sistemas financeiros. Teríamos que duplicar muito mais tabelas e relacionamentos, e a base de código aumentaria significativamente. No entanto, posso ver a necessidade no seu caso.
Jonh
Duplicar as tabelas não é um problema se as tabelas de auditoria são automaticamente implantadas e mantidas em sincronia - o mesmo com o código, bastava fornecer um injetor na camada de dados para alternar entre as tabelas de auditoria e as tabelas ativas - todas as consultas permaneceu o mesmo.
Michael
Michael, se você não se importa em perguntar qual o tamanho da sua equipe de desenvolvedores para um projeto como esse?
Jonh
Foi há um tempo atrás, então não tenho 100% de certeza, mas acho que 4 desenvolvedores, 3 testadores e 1 analista.
Michael
1

Faça isso explicitamente na instrução delete / undelete. Provavelmente, também existem vários cenários em que você não deseja colocar em cascata a exclusão.

> Update table1 set deleted=@flag where...
> Update table2 set deleted=@flag where...

Por exemplo; considere uma pessoa com vários endereços.

Para excluir a pessoa, basta definir o sinalizador Excluir na pessoa. Não há necessidade de colocar em cascata a exclusão nos endereços, porque quando restauramos, queremos esses endereços de volta.

Digamos que a pessoa se mudou, então queremos atualizar o sinalizador de exclusão apenas no endereço antigo, deixando os outros endereços e a pessoa sozinhos. Portanto, a cascata nem sempre é necessária e depende do cenário.

Então, acho que você precisa ser explícito, dependendo de como seu modelo está configurado e de qual sua exclusão.

Jon Raynor
fonte
1
A integridade não deve ser mantida pelo banco de dados (com um gatilho), em vez de esperar que o programador de aplicativos esteja ciente de todos os relacionamentos entre as tabelas e o que precisa cascatear para onde?
@ MichealIT - Não há integridade de dados aqui, porque está simplesmente atualizando uma coluna. Você está certo de que a atualização pode ser acionada, mas defini-la explicitamente com uma operação de exclusão (SP) facilitaria a localização. No acionador, seria necessário interrogar o sinalizador Excluir e tomar as medidas apropriadas para determinar se era 1 ou 0. A lógica do acionador tende a ser mais obscura, em oposição a um procedimento armazenado.
precisa saber é o seguinte
@MichealT - Neste exemplo, a menos que o registro de endereço deva ser "excluído", deixe-o em paz. No sentido do banco de dados relacional, você ainda mantém a integridade relacional porque todos esses registros ainda existem. São as regras de negócios que optam por excluí-las. E sim, um desenvolvedor entende melhor como todas essas exclusões virtuais são tratadas.
JeffO 9/01/14