Por que as restrições são aplicadas no banco de dados? Não será mais flexível inseri-lo no código?
Estou lendo um livro para iniciantes sobre a implementação de bancos de dados, então estou perguntando isso como iniciante. Digamos que eu projetei um banco de dados, incluindo este modelo de entidade:
entity type | sub-types
----------------+--------------------------------------------
Person | Employee, Student, ...
Student | Graduate, Undergraduate, ...
Employee | Teacher, Administrator, ...
Restrições atuais:
- Uma pessoa registrada no sistema pode ser apenas um Estudante ou um Funcionário.
- A entidade pessoa requer exclusividade de número social, que presumimos que cada pessoa possua apenas um único (ou seja, uma chave primária suficientemente boa ). (veja nº 1)
Mais tarde, decidimos remover o número 1: se um dia a faculdade decidir que o Teacher
(o Employee
subtipo) também pode ser Student
, fazendo cursos em seu tempo livre, é muito mais difícil alterar o design do banco de dados, que pode ter milhares, milhões, bilhões, zilhões de entradas em vez de apenas alterar a lógica do código: apenas a parte que não permitia que uma pessoa fosse registrada como estudante e como funcionário.
(É muito improvável, mas não consigo pensar em mais nada no momento. Aparentemente é possível).
Por que nos preocupamos com as regras de negócios no design do banco de dados, e não no código?
Nº 1: Uma nota 7 anos depois, um exemplo da vida real:
eu vi um governo em que, devido a um erro, os SSNs emitidos foram duplicados: várias pessoas, o mesmo SSN. Aqueles que projetaram o banco de dados original definitivamente cometeram o erro de não aplicar essa restrição de exclusividade no banco de dados. (e depois um bug no aplicativo original - vários aplicativos usando o banco de dados compartilhado e não concordando onde colocar, verificar e impor a restrição? ...).
Este bug continuará a viver no sistema e todo o sistema desenvolvido após o qual confiar no banco de dados do sistema original, por muitos e muitos anos. Lendo as respostas aqui, aprendi a aplicar todas as restrições, o maior número possível, sabiamente (não cegamente) no banco de dados para representar o mundo físico real lá fora, o melhor que posso.
fonte
Respostas:
Algumas restrições são melhor aplicadas no banco de dados e outras são melhor aplicadas no aplicativo.
As restrições que são melhor aplicadas no banco de dados geralmente existem porque são fundamentais para a estrutura do modelo de dados, como uma contraint de chave estrangeira para garantir que um produto tenha uma validade
category_id
.As restrições impostas em um aplicativo podem não ser fundamentais para o modelo de dados, como todos os produtos FooBar devem ser azuis - mas mais tarde alguém pode decidir que o FooBars também pode ser amarelo. Essa é a lógica do aplicativo que realmente não precisa estar no banco de dados, embora você possa criar uma
colours
tabela separada e o banco de dados possa exigir que o produto faça referência a uma entrada válida dessa tabela. MAS a decisão de que o único registro emcolours
tem o valorblue
seria ainda vir de algum lugar fora do banco de dados.Considere o que aconteceria se você não tivesse restrições no banco de dados e exigisse que todas fossem aplicadas no aplicativo. O que aconteceria se você tivesse mais de um aplicativo que precisava trabalhar com os dados? Como seriam seus dados se os diferentes aplicativos decidirem aplicar restrições de maneira diferente?
Seu exemplo mostra uma situação em que poderia ter sido mais benéfico ter a restrição no aplicativo do que no banco de dados, mas talvez houvesse um problema fundamental com o modelo de dados inicial sendo muito restritivo e inflexível?
fonte
teachers_as_students
que é outro subtipoStudents
e que possui uma nova chave estrangeira referente aTeachers
uma chave primária gerada pelo sistema , em vez de uma Social Número de segurança. Dessa forma, um "aluno" na verdade é um apelido para um professor, para que ele ainda possa se registrar para assistir a uma aula. É difícil dizer com certeza o quão bem isso funcionaria sem ver todo o modelo de dados.color_products
, ecolor
provavelmente poderá criar as listas suspensas adicionais com mais facilidade - a maioria dos IDEs / carregadores de esquema suporta as seguintes chaves.Porque:
Apenas algumas razões que são importantes para mim.
fonte
Os dados provavelmente sobreviverão por muito tempo ao código do aplicativo. Se a regra for crítica para que os dados sejam úteis ao longo do tempo (como restrições de chave estrangeira que ajudam a manter a integridade dos dados), ela deve estar no banco de dados. Caso contrário, você corre o risco de perder a restrição em um novo aplicativo que atinge o banco de dados. Não apenas vários aplicativos atingem bancos de dados (incluindo alguns que podem não perceber que existe uma regra de dados importante), mas alguns deles, como importações de dados ou aplicativos de relatório, podem não ser capazes de usar a camada de dados configurada no aplicativo de entrada de dados principal. Francamente, as chances de haver um bug na restrição são muito maiores no código do aplicativo na minha experiência.
Na minha opinião pessoal (com base em mais de 30 anos lidando com dados e experiência com centenas de bancos de dados diferentes usados para diversos fins), qualquer pessoa que não coloque as restrições no banco de dados a que pertence, acabará por ter poucos dados. Às vezes, dados ruins a ponto de ficarem inutilizáveis. Isso é especialmente verdade quando você tem dados financeiros / regulatórios que precisam atender a certos critérios de auditoria.
fonte
A maioria das restrições de integridade referenciais implementadas fora do banco de dados pode ser derrotada. Portanto, se você deseja que seus dados tenham integridade garantida o tempo todo, é necessário aplicar restrições no banco de dados. Ponto final, é isso.
Normalmente, as restrições no nível do aplicativo são derrotadas pelo mecanismo de consistência de leitura do banco de dados, pelo qual as sessões não podem exibir os dados de outras sessões até que sejam confirmadas.
Por exemplo, duas sessões podem tentar inserir o mesmo valor em uma coluna que se destina a ser exclusiva. Ambos podem verificar ao mesmo tempo que o valor ainda não existe, podem inserir seu valor e podem confirmar. Uma restrição exclusiva implementada no banco de dados não deixaria isso acontecer.
A propósito, isso não é desconhecido para os designers de linguagem de aplicativos. Leia a exclusividade da seção 3.10 nos Guias do Ruby on Rails: validações de registro ativas e retornos de chamada
fonte
Benefícios das restrições impostas pelo banco de dados:
Simplicidade - declarar uma restrição é significativamente mais simples do que declarar uma restrição e escrever o código que aplicará essa declaração.
Precisão - o código que você não escreveu nunca terá um bug que você criou. Os fornecedores de banco de dados gastam tempo certificando-se de que seu código de restrição é preciso, para que você não precise.
Velocidade - seu aplicativo nunca pode ter mais distribuições do que o banco de dados em que se baseia. Os fornecedores de banco de dados gastam tempo certificando-se de que seu código de restrição seja eficiente, para que você não precise. O próprio banco de dados também tem acesso mais rápido aos dados do que um aplicativo poderia ter, por mais eficiente que fosse.
Reutilização - Você pode começar com um aplicativo em uma plataforma, mas pode não continuar assim. E se você precisar acessar os dados de um SO diferente, hardware diferente ou de uma interface de voz? Por ter restrições no banco de dados, esse código nunca precisa ser reescrito para a nova plataforma e nunca deve ser depurado por precisão ou perfilado por velocidade.
Completude - Os aplicativos impõem restrições quando os dados são inseridos no banco de dados e exigiriam um esforço adicional para verificar se os dados mais antigos são precisos ou para manipular os dados que já estão no banco de dados.
Longevidade - Sua plataforma de banco de dados provavelmente sobreviverá a qualquer aplicativo específico.
fonte
Por que as restrições são aplicadas no servidor? Porque você não pode forçar os bandidos a usar seu cliente.
Para esclarecer, se você estiver executando apenas o processamento de regras de negócios em seu aplicativo cliente, alguém usando outra ferramenta poderá se conectar ao servidor de banco de dados e fazer o que quiser, sem ser restringido por nenhuma das regras de negócios e verificações de integridade. Impedir alguém de usar uma ferramenta arbitrária em qualquer lugar da rede é muito difícil.
Se você fizer a verificação de integridade no servidor de banco de dados, todas as tentativas de acessar dados, independentemente da ferramenta, serão restringidas por suas regras.
fonte
Algumas ótimas respostas aqui e com o risco de repetir outros pensamentos:
UPDATE
instrução diretamente no banco de dados, como seu aplicativo impede uma alteração inválida? Outro problema com as regras de negócios no aplicativo é que a recompilação / reimplantação pode ser difícil, especialmente para aplicativos distribuídos, onde é possível que nem todos recebam a atualização ao mesmo tempo. E, finalmente, alterar as regras de negócios no aplicativo não faz absolutamente nada sobre os dados que já existem que violam as novas regras - se você adicionar a nova restrição aos dados, precisará corrigi-los.No caso de você mencionar explicitamente, onde de repente você está permitindo algo que não era permitido anteriormente, isso não é realmente um problema - você remove qualquer restrição imposta, independentemente de onde isso exista. No caso oposto, onde de repente os professores não podem mais ser alunos, você potencialmente tem um monte de dados para limpar, novamente independentemente de onde a restrição existia anteriormente.
fonte
O banco de dados pode verificar as restrições efetivamente. Melhor que o código.
As restrições de integridade ajudam o banco de dados a encontrar um plano de execução eficaz
O aplicativo vê uma visualização consistente da leitura, portanto, dificilmente pode garantir exclusividade. Embora o banco de dados também possa ver dados não confirmados.
fonte
Resposta curta ... para preservar a integridade dos dados (ou seja, precisão e validade).
Uma exceção ...
Se o banco de dados estiver apenas armazenando os dados de um único aplicativo para um único usuário, como na maioria dos bancos de dados Sqlite, ele pode não precisar de restrições. Na verdade, eles geralmente não o fazem, para manter o tempo de acesso tão rápido que é incomensurável.
Para todo o resto ... Os
bancos de dados sempre atendem a dois mestres que chamarei de editores e usuários .
Os editores geralmente colocam dados no banco de dados e recuperam dados um ou um pequeno número de registros por vez. Suas principais preocupações são o acesso rápido e preciso a todos os dados relacionados e o armazenamento rápido e confiável de suas alterações.
Os usuários geralmente recuperam dados e estão mais preocupados com o acesso rápido a informações inquestionavelmente precisas. Eles geralmente precisam de várias contagens, agregações e listagens que costumavam ser geradas naquelas pilhas icônicas de impressões em papel greenbar, mas geralmente acabam nas páginas da web hoje.
Os projetos de desenvolvimento de banco de dados quase sempre são iniciados por ordem dos Usuários , mas o design é orientado pelas necessidades de entrada de dados e registro por vez dos Editores . Dessa forma, desenvolvedores inexperientes geralmente respondem à necessidade imediata de velocidade (principalmente do desenvolvimento ), não colocando restrições no banco de dados.
Se um e apenas um aplicativo for usado para fazer alterações nos dados por toda a vida útil do banco de dados, e esse aplicativo for desenvolvido por um ou um pequeno número de indivíduos bem coordenados, pode ser razoável contar com o aplicativo para garantir a integridade dos dados.
No entanto, por mais que fingimos que podemos prever o futuro, não podemos.
O esforço para produzir qualquer banco de dados é valioso demais para ser descartado. Como uma casa, o banco de dados será estendido, alterado e renovado várias vezes. Mesmo quando for completamente substituído, todos os dados serão migrados para o novo banco de dados, preservando todas as regras e relacionamentos de negócios antigos.
As restrições implementam essas regras e relacionamentos de forma declarativa e concisa no próprio mecanismo de banco de dados, onde são facilmente acessados. Sem eles, os desenvolvedores subsequentes precisariam passar pelos programas aplicativos para fazer engenharia reversa dessas regras. Boa sorte!
A propósito, é exatamente isso que os programadores COBOL de mainframe precisam fazer, pois esses bancos de dados maciços costumavam ser criados antes de termos restrições e mecanismos relacionais. Mesmo se migrados para um sistema moderno como o DB2 da IBM, as restrições às vezes não são totalmente implementadas, já que a lógica das regras antigas, incorporadas talvez em uma série de programas "batch" de COBOL, pode ser tão complicada que não é prática a conversão. Em vez disso, ferramentas automatizadas podem ser usadas para converter o antigo COBOL em uma versão mais recente, com interfaces para o novo mecanismo relacional e com um pouco de ajustes, a integridade dos dados é preservada ... até que um novo aplicativo seja escrito que corrompa sutilmente tudo e a empresa seja transportada no tribunal por, por exemplo, excluir milhares de proprietários de casas que eles não deveriam ter.
fonte
Além dos outros comentários ...
Se / quando você tiver um banco de dados em que qualquer tabela possa ser atualizada por um ou mais aplicativos ou caminhos de código, a colocação das restrições apropriadas no banco de dados significa que seus aplicativos não duplicarão o "mesmo" código de restrição. Isso beneficia você simplificando a manutenção (reduzindo o número de locais a serem alterados se / quando houver uma alteração no modelo de dados) e garante que as restrições sejam aplicadas de forma consistente, independentemente do aplicativo que atualiza os dados.
fonte
Pessoalmente, acho que é mais fácil criar e alterar restrições do que criar gatilhos, por exemplo, que seria uma maneira de impor sua regra de negócios usando o código-fonte.
Também é menos provável que os acionadores sejam portáteis, pois geralmente são escritos em linguagens específicas do fornecedor, como PL / SQL.
Mas se as restrições não atenderem às suas necessidades, você sempre poderá usar gatilhos para impor suas regras de negócios.
fonte
Eles sempre devem ser aplicados no banco de dados primeiro porque,
varchar(5)
tipo, há uma boa chance de encontrar um esquema carregando ORM para seu idioma específico que mapeia o tipo de idioma para o tipo do esquema e monta sua própria restrição de tamanho.DBIx for Perl is one such schema loader
; aqui está outro para o Entity Framework . As habilidades desses carregadores variam, mas tudo o que eles podem fornecer é um bom começo para garantir a integridade do aplicativo sem a necessidade de ir ao banco de dados.fonte