Existe uma razão convincente para que as colunas no SQL sejam anuláveis ​​por padrão?

8

Como estudante de CS, aprendi um número decente de linguagens de programação ao longo dos anos, a maioria das quais teve algum conceito de tipo "anulável" ou "opcional". Note que estou não falar de ponteiros nulos ou referências, ou linguagens fracamente tipadas como JavaScript, onde tudo pode ser null. Exemplos do que estou falando incluem boost::optional(C ++), java.util.Optional(Java 8.0), prelude.Maybe(Haskell) e todos os '?' tipos (por exemplo int?, float?C # e Kotlin). Essas são construções que adicionam capacidade de anulação a um tipo anteriormente não anulável em um sistema de tipo estático estrito.

O SQL tem um conceito semelhante: um tipo como INTEGERpode ser anulável ou não anulável - mas há uma diferença. No SQL, INTEGERé anulável por padrão e deve ser explicitamente gravada como INTEGER NOT NULLpara não ser anulável.

Parece-me extremamente contra-intuitivo e potencialmente perigoso por permitir que o NULL seja o comportamento padrão. Obviamente, o SQL existe há tanto tempo neste ponto que (a maioria) os desenvolvedores de SQL desenvolveram uma percepção saudável das armadilhas do NULL. Mas não posso deixar de imaginar que, nos primeiros dias, os NULL costumavam aparecer em lugares inesperados e problemáticos.

O SQL antecede todos os exemplos que forneci, portanto, é possível que isso seja apenas uma questão de evolução histórica. Ainda assim, devo perguntar, existe alguma boa razão para o idioma ser projetado dessa maneira, com tipos sendo anuláveis ​​por padrão?

Em caso afirmativo, é apenas uma razão histórica ou a lógica é válida para o design de banco de dados hoje?

Edit: Não estou perguntando por que NULL faz parte do SQL ou por que colunas anuláveis ​​são úteis. Estou apenas perguntando por que a coluna é anulável por padrão . Por exemplo, por que escrevemos:

column1 FLOAT,
column2 FLOAT NOT NULL

Ao invés de:

column1 FLOAT NULLABLE,
column2 FLOAT
AproximandoEscuridãoPeixe
fonte
2
Aprenda a aceitar esta resposta: "Não há motivo, é apenas nossa política".
2
Porque às vezes o conceito de "eu não sei" deve ser representado no banco de dados de forma clara
Newtopian
@ Newtopian, que explica por que NULL está no idioma. Estou perguntando por que NULL é permitido colunas por padrão.
ApproachingDarknessFish
4
Porque "eu não sei" é surpreendentemente comum nas informações do banco de dados. Para ilustrar esse ponto por um exemplo. Imagine formulários da web onde TODOS os campos são obrigatórios por padrão e como isso seria irritante. Em um banco de dados, você PRECISA preencher TODOS os campos com alguma coisa, sempre. No entanto, na representação do seu domínio, é muito provável que muitas dessas informações não sejam essenciais e possam ser deixadas "desconhecidas" sem efeitos negativos (desde que você proteja seu código adequadamente). Na verdade, eu apostaria que, na maioria das aplicações, a maioria das informações se enquadra nessa categoria não essencial, daí o padrão observado.
Newtopian
@Newtopian Tudo bem. Faça essa resposta.
ApproachingDarknessFish

Respostas:

24

Na Uni fui ensinado que o oposto é verdadeiro. É muito mais perigoso fazer algo not nullsem razão. Com um campo anulável, a pior coisa que pode acontecer é você tropeçar no aplicativo que acessa os dados. Oh querida, volte e corrija o aplicativo ...

Com um campo não nulo, você torna impossível adicionar registro porque algum campo arbitrário não está disponível. Agora você precisa alterar o modelo de dados e potencialmente corrigir o resultado em vários lugares diferentes ...

É bom pensar nullem "desconhecido". Se houver algum motivo plausível para você inserir um registro sem saber algo, ele deverá ser anulado.

Um dos meus professores da universidade descreveu assim:

Apócrifamente, ouvi falar de um sistema de vendas nos EUA que exigia o número de segurança social do cliente para fazer uma venda. Todos os operadores de caixa registradora fizeram quando um estrangeiro veio para a caixa registradora digitar 000-00-0000. Mas então outros entrariam em 123-45-6789. Isso impossibilita a identificação de lixo eletrônico. É muito melhor permitir que um campo fique em branco do que forçá-lo a conter lixo.

Ou outra história. Eu realmente fui recusado pelo seguro de carro porque não tenho dois números de telefone. Eles absolutamente não me dariam seguro a menos que eu lhes desse dois. O vendedor sugeriu que eu desse uma falsa. No final, eu me recusei a mentir para uma seguradora e apenas fui com outra empresa.

Na prática, reserve os not nullcampos necessários para entender o registro. Por exemplo:

Uma tabela de locais com campos (ID, nome do local, país, longitude, latitude) ... "longitude" "latitude" deve ser anulável para que você possa armazenar a existência de um local antes de saber onde ele está.

Mas se você tiver uma tabela cujo único objetivo é armazenar coordenadas geográficas com campos (Item_id, longitude, latitude), todo o registro não terá sentido se a longitude e a latitude forem nulas. Portanto, nesse caso, eles devem ser não nulos

Na minha experiência profissional desde a uni, há muito mais campos que podem ser opcionais do que precisam ser obrigatórios.

Philip Couling
fonte
Quem você está citando no bloco de cotação acima?
Robert Harvey
Palestrante de universidade.
Philip Couling
8

Parece-me extremamente contra-intuitivo ...

Intuitivo está nos olhos de quem vê e sua opinião é moldada pelas coisas a que você foi exposto. Sou de uma época em que esse tipo de segurança não era padrão e as ferramentas não apontavam quando você brincava. Estou usando a motosserra sem uma proteção de lâmina há tempo suficiente para que meu primeiro instinto seja evitar completamente a intuição, voltar ao DDL e descobrir exatamente quais suposições o esquema me permitirá fazer sobre seus dados.

... e potencialmente perigoso por permitir que o NULL seja o comportamento padrão.

Eu acho que você está exagerando os perigos relativos. NOT NULLtem seu próprio conjunto de armadilhas que podem levar a erros igualmente insidiosos. (Enumerá-los seria forragem para uma pergunta diferente.)

O designer de uma tabela sempre tem a opção de restringir uma coluna NULLou NOT NULLe fará uma ou outra para contornar o padrão, seja ele qual for. Não restringir uma coluna corretamente é uma falha do desenvolvedor em seguir as regras de negócios. Não fazer a coisa certa em outro lugar, com base na definição da coluna, é a falha do desenvolvedor em entender os dados que estão sendo entregues. Também não há correção técnica.

Ainda assim, devo perguntar, existe alguma boa razão para o idioma ser projetado dessa maneira, com os tipos sendo anuláveis ​​por padrão?

Não, não existe. Como ambos apresentam riscos, também não há uma boa razão para o idioma ser projetado de outra maneira. Tudo se resume a escolher o seu veneno.

Blrfl
fonte
6

As colunas anuláveis ​​são necessárias no SQL devido a junções externas (também conhecidas como junções à esquerda ou junções à direita). Quando a linha de um lado da junção não possui correspondência do outro lado, os campos do outro lado devem ter NULLs. Como a saída de uma junção pode ter colunas anuláveis, as tabelas base também devem suportá-las devido ao princípio do fechamento relacional (que basicamente declara que o resultado de uma consulta ou exibição deve ser indistinguível de uma tabela base).

Diante disso, o SQL deve suportar colunas anuláveis. Por outro lado, colunas não anuláveis ​​são um recurso secundário - o SQL ainda pode funcionar sem elas.

JacquesB
fonte
4

Vamos virar e dizer que você está certo. Digamos que seu número inteiro não seja nulo por padrão.

O que significa que ele deve ter um valor por padrão. Mesmo quando não se sabe.

Portanto, quando você atualiza a tabela de pessoas e tem duas opções: É impossível atualizar a tabela porque você não inseriu peso. Ou quando você não forneceu o argumento de peso, ele colocou no padrão "-1 quilos" quando desconhecido.

Ambas as situações são indesejáveis. Você deseja adicionar clientes, mesmo que não saiba o peso deles. Mas também, você não deseja ter valores "proxy". Valores que são espaços reservados, mas que podem ter um significado real, por exemplo: podem ser usados ​​em funções matemáticas como "média", mas não são valores reais.

Quero dizer, ao calcular um peso médio, -1 é um valor válido na sua função média matemática, mas não como o peso das pessoas. Você usa null e agora sua função média sabe ignorar esse valor.

Além disso, eu realmente não compararia o SQL às linguagens de programação ao discutir nulos, eles são inerentemente diferentes, o nulo no SQL faz parte da teoria do design de banco de dados relacional.

Pieter B
fonte
3

Não. Não existe um motivo convincente para o SQL usar como padrão nulo. De fato, muitos pesquisadores proeminentes na teoria de bancos de dados relacionais discordaram dessa decisão de design, talvez mais notavelmente Chris Date , um colaborador frequente do criador original do banco de dados relacional, Edgar Codd . Date (junto com o co-autor Hugh Darwen) publicou um livro bem conhecido sobre teoria relacional (" O Terceiro Manifesto ") que descreve princípios para projetos alternativos para uma família de idiomas relacionais que eles chamam de "D", juntamente com um exemplo chamado " Tutorial D ".

Linguagens D são proibidas explicitamente de suportar valores NULL ("D não incluirá nenhum conceito de uma" relação "na qual alguma" tupla "inclua algum" atributo "que não tenha um valor."). Em vez disso, os valores opcionais são suportados por tipos de dados alternativos que incluem marcadores "não presentes" ou valores semelhantes. As linguagens D fornecem um modelo rico para tipos definidos pelo usuário que permitem que qualquer tipo nativo seja estendido com esses valores extras.

Existem razões teóricas convincentes para que essa seja uma boa ideia, e Date & Darwen escreveram muito sobre isso, bem como outras decisões que tomaram em seu design. Eu recomendo ler o trabalho deles sobre esse tópico.

Jules
fonte
1
Não sigo / não concordo com sua lógica. Eu acredito que você está confundindo duas questões separadas. Questão a) um idioma deve representar nulo? Problema b) em um idioma que use null para significar "não presente" os campos devem permitir nulo (não presente) por padrão? Talvez você perdeu um passo em sua resposta ... Existe uma alínea c) Em D, atributos não deve permitir que não-presente por padrão porque .... <inserir argumento aqui>
Philip Couling
2
Meu primeiro comentário é difícil de seguir, então vou colocar de forma simples: Representing x with null is a bad ideanão infere isso allowing x by default is bad. Ergo isso não implica queallowing null by default is bad where null is the only available representation of x
Philip Couling
1
@jules: qual é a diferença conceitual entre um campo int ser anulável e um campo int com um tipo de dados alternativo: 'não presente'? Não é a mesma coisa com um nome diferente? Nulo também é um tipo de dados alternativo ao int.
Pieter B
1
@PieterB Sim e não. O problema fundamental do nulo é que ele é usado para significar muitas coisas diferentes. No SQL, poderia significar "não existe" ou "desconhecido". O argumento D é que todos devem ser definidos de maneira distinta e um "nulo" genérico nunca deve ser usado. Não ter estudado em detalhe, eu suspeito que os defensores da D defenderia Not Present = Not Presentonde em SQL nem null = nullou null != nullsão verdadeiras.
Philip Couling
Codd disse que deveria haver mais tipos de Null, acho que ele propôs 4 inicialmente e depois expandiu para 17. Os programadores disseram: Por que estamos desperdiçando esforços para distinguir maneiras de dizer "eu não sei"? Certamente, existem incógnitas conhecidas e incógnitas desconhecidas, mas, na verdade, os dados são conhecidos, e não muito mais.
1

Não discordo de sua premissa sobre qual deve ser o padrão, mas é uma boa prática não assumir nada como desenvolvedor. Verificar as especificações em uma tabela de banco de dados não deve ser muito difícil.

Mais do ponto de vista do DBA, no qual você seria solicitado a carregar dados em massa, especialmente ao mesclar a partir de outros sistemas, é melhor conhecer a configuração de cada campo, se você tem dados para inserir ou não.

Negócios e aplicativos são administrados por pessoas. Se eles não são programadores, a definição de "nunca" e "sempre" não é exatamente a mesma e mudará com o tempo. A configuração nula atual em um determinado campo não deve ser confusa.

JeffO
fonte
Certo, o carregamento em massa, a migração etc. acabam superando todas as outras preocupações, porque os dados são reais e de valor, e os programas são apenas ferramentas temporárias que os moldam. Alguém viu um cartão perfurado ou as máquinas de gravação do censo de 1900? Não, mas os dados ainda estão disponíveis. Quantas vezes foi movido de um sistema para outro, mesmo no ano passado? Toda vez que alguém usa, suponho.
0

Bancos de dados são bestas diferentes das linguagens de programação normais.

Como o esquema de uma tabela é definido, todos os dados precisam estar presentes ao salvar as informações em uma linha. No entanto, muitos desses dados podem não ser necessários para criar uma representação válida de um objeto de modelo, uma vez carregado no seu código. Exigir que todos os dados sejam não nulos e preenchidos significará que esses campos não obrigatórios deverão conter um valor e, ainda assim, ainda não possuem um, eles são "desconhecidos".

Imagine ter que preencher TODOS os campos nos formulários da Web o tempo todo, já que eles não podem ser nulos no banco de dados, eles devem receber um valor ... uma receita de insanidade!

Você pode definir alguns valores reservados para representar a ausência de dados, uma sequência vazia, um número específico, uma data específica etc., dependendo do tipo de dados, mas que valor escolher? Então você precisa garantir que todos concordem que esses valores arbitrários realmente significam "desconhecido" e não "1º de janeiro de 1970", por exemplo. A aversão nula pode assumir várias formas e levá-lo a desvios longos e complicados, apenas porque alguém disse que os nulos eram ruins. Quão complexo você está pronto para ficar apenas para evitar lidar com nulos?

Tendo um único valor universal para tudo o que é desconhecido, acho muito preferível do que usar algum conjunto de valores constantes arbitrários. Não estou dizendo que valores constantes são ruins e nulo é melhor, se seu modelo é bem servido por uma constante para representar essas informações, use-o de qualquer maneira, mas existem muitas situações em que um nulo é exatamente o que melhor se encaixa. Para todos os haters nulos, esta é uma situação se nulo foi negado, teria que ser inventado!

Vendo quão difundido é o conceito de "desconhecido" em um banco de dados, sim, eu diria que tornar os valores nulos um padrão faz muito sentido.

Aprofundando e analisando outras respostas aqui, não ficaria surpreso ao saber que os nulos não são apenas um "recurso de linguagem", mas uma parte integrante da teoria subjacente na qual o SQL se baseia. Pode-se remover C (a velocidade da luz) da relatividade, mas o conceito de velocidade máxima absoluta permanece e ainda deve ser expresso, para que volte de alguma forma ou forma.

Newtopian
fonte
0

Resposta curta: compatibilidade com versões anteriores.

Resposta longa:

Em um banco de dados totalmente normalizado, NULL não é permitido em nenhuma coluna. Por exemplo, suponha que exista uma tabela chamada MailingAddress que tenha uma coluna PostOfficeBox, que é um número inteiro. Como nem todo mundo tem uma caixa postal, existem duas maneiras de implementar isso.

Primeiro, NULL pode ser permitido na coluna.

Segundo, PostOfficeBox é removido do MailingAddress e uma nova tabela, PostOfficeBox é criada com uma coluna Number e seu PK sendo o FK para MailingAddress. Mas agora são necessárias duas consultas para obter endereços para correspondência: uma para quem não tem caixas postais e outra para quem tem.

O SQL permite NULLs em colunas para propósitos práticos.

shawnhcorey
fonte