SQL: string vazia versus valor NULL

69

Eu sei que este assunto é um pouco controverso e há vários artigos / opiniões flutuando na internet. Infelizmente, a maioria deles assume que a pessoa não sabe qual é a diferença entre NULL e string vazia. Então, eles contam histórias sobre resultados surpreendentes com junções / agregados e geralmente fazem lições de SQL um pouco mais avançadas. Ao fazer isso, eles absolutamente perdem todo o ponto e, portanto, são inúteis para mim. Então esperamos que esta pergunta e todas as respostas se movam um pouco para frente.

Vamos supor que eu tenha uma tabela com informações pessoais (nome, nascimento, etc) onde uma das colunas é um endereço de e-mail com o tipo varchar. Presumimos que, por alguma razão, algumas pessoas podem não querer fornecer um endereço de e-mail. Ao inserir tais dados (sem email) na tabela, há duas opções disponíveis: definir cell para NULL ou defini-la como string vazia (''). Vamos supor que eu esteja ciente de todas as implicações técnicas de escolher uma solução sobre outra e posso criar consultas SQL corretas para qualquer cenário. O problema é que, mesmo quando os dois valores diferem no nível técnico, eles são exatamente os mesmos no nível lógico. Depois de olhar para NULL e '' cheguei a uma única conclusão: eu não sei o endereço de e-mail do cara. Também, não importa o quanto eu tentei, não consegui enviar um e-mail usando NULL ou string vazia, então aparentemente a maioria dos servidores SMTP concordam com minha lógica. Então eu costumo usar NULL onde eu não sei o valor e considero uma string vazia uma coisa ruim.

Depois de algumas discussões intensas com colegas, venho com duas perguntas:

  1. estou certo em assumir que usar uma string vazia para um valor desconhecido está fazendo com que um banco de dados "minta" os fatos? Para ser mais preciso: usando a idéia do SQL sobre o que é valor e o que não é, posso chegar à conclusão: temos endereço de e-mail, apenas descobrindo que não é nulo. Mas, mais tarde, ao tentar enviar e-mail, chego a uma conclusão contraditória: não, não temos endereço de e-mail, que @! # $ O banco de dados deve estar mentindo!

  2. Existe algum cenário lógico no qual uma string vazia '' poderia ser uma boa portadora de informações importantes (além de valor e sem valor), o que seria problemático / ineficiente para armazenar de qualquer outra forma (como adicional coluna). Eu vi muitos posts afirmando que às vezes é bom usar string vazia junto com valores reais e NULLs, mas até agora não vi um cenário que seria lógico (em termos de design SQL / DB).

P.S. Algumas pessoas ficarão tentadas a responder que é apenas uma questão de gosto pessoal. Eu não concordo. Para mim, é uma decisão de design com consequências importantes. Então, eu gostaria de ver respostas onde opion sobre isso é apoiado por algumas razões lógicas e / ou técnicas.

    
por Jacek Prucia 30.12.2010 / 13:10
fonte

12 respostas

82

Eu diria que NULL é a escolha correta para "nenhum endereço de e-mail". Existem muitos endereços de email "inválidos" e "" (cadeia vazia) é apenas um. Por exemplo, "foo" não é um endereço de email válido, "a @ b @ c" não é válido e assim por diante. Então, só porque "" não é um endereço de e-mail válido, não há razão para usá-lo como o valor "sem endereço de e-mail".

Eu acho que você está certo em dizer que "" não é a maneira correta de dizer "Eu não tenho um valor para esta coluna". "" é um valor.

Um exemplo de onde "" pode ser um valor válido, separado para NULL poderia ser o nome do meio de uma pessoa. Nem todo mundo tem um nome do meio, então você precisa diferenciar entre "sem nome do meio" ("" - string vazia) e "não sei se essa pessoa tem um nome do meio ou não" ( NULL ). Há provavelmente muitos outros exemplos em que uma string vazia ainda é um valor válido para uma coluna.

    
por 30.12.2010 / 13:22
fonte
41

Ao concordar com os comentários acima, eu adicionaria esse argumento como uma motivação primária:

  1. É óbvio para qualquer programador que esteja vendo em um banco de dados que um campo marcado como NULL é um campo Opcional. (ou seja, o registro não requer dados para essa coluna)
  2. Se você marcar um campo NOT NULL, qualquer programador deve assumir intuitivamente que é um campo Obrigatório.
  3. Em um campo que permite nulos, os programadores devem esperar ver valores nulos em vez de sequências vazias.

Para fins de Auto-Documentação de Codificação Intuitiva, use NULL em vez de strings vazias.

    
por 14.09.2011 / 23:30
fonte
6

No seu exemplo, se é um valor diretamente do campo da web - eu usaria uma string vazia. Se o usuário tiver a opção de especificar que ele não deseja fornecer um e-mail ou excluí-lo, NULL.

Este é o link com os pontos que você pode considerar: link

--- editado (Em resposta ao comentário de Thomas) ---

Bancos de dados não vivem sem aplicativos que os utilizam. Definir NULL ou '' não tem valor, se o aplicativo não puder usá-lo corretamente.

Considere um exemplo em que o usuário está preenchendo o formato LONG e pressione Enter, que enviará uma solicitação persistente ao servidor. Ele poderia estar no meio de entrar em seu email. Muito provavelmente você quer armazenar tudo o que ele tem no campo de email, então mais tarde ele poderia terminá-lo. E se ele entrasse em apenas um personagem? E se ele inserisse um caractere e depois apagasse? Quando o e-mail não é necessário, às vezes, os usuários querem excluí-lo: a maneira mais fácil de limpar o campo. Também no caso de não ser necessário e-mail, vale a pena validá-lo antes de enviar.

Outro exemplo: o usuário fornece e-mail como spam para @ [bigcompany] .com - nesse caso, não há necessidade de enviar e-mail, embora ele exista e seja válido (e pode até existir). Enviar um desses talvez seja barato, mas se houver 10 mil usuários com esses e-mails para assinaturas diárias, essa validação poderá economizar muito tempo.

    
por 30.12.2010 / 13:41
fonte
4

Use nulo.

Não há sentido em armazenar um valor de '', quando simplesmente tornar o campo na tabela anulável. Isso torna as consultas mais óbvias também.

Qual consulta SQL é mais óbvia e legível se você quiser encontrar usuários com um endereço de e-mail?

  1. SELECT * FROM Users WHERE email_address != ''

  2. SELECT * FROM Users WHERE email_address IS NOT NULL

  3. SELECT * FROM Users WHERE email_address != '' and email_address IS NOT NULL

Eu diria que 2 é. Embora 3 seja mais robusto nos casos em que há dados incorretos armazenados.

Para o caso do endereço de email no formulário, que é opcional, deve ser refletido na tabela também. No SQL, é um campo anulável, o que significa que não é conhecido.

Eu não consigo pensar em nenhum valor comercial razoável ao armazenar uma string vazia em uma tabela que não seja simplesmente um design ruim. É como armazenar um valor de string de 'NULL' ou 'BLANK', e ter os desenvolvedores assumindo que é null ou uma string vazia. Para mim, isso é um design ruim. Por que armazenar isso quando há NULL ??

Use NULL e você ficará mais feliz para todos.

MAIS INFORMAÇÃO:

O SQL usa um sistema lógico de três valores: True, False e Unknown.

Para uma explicação melhor e mais detalhada, recomendo que os desenvolvedores leiam: Consultas SQL - além de TRUE e FALSE .

    
por 15.09.2011 / 00:17
fonte
4

Eu acho que a resposta do Dean Hardings cobre isso muito bem. Dito isso, gostaria de mencionar que, ao falar sobre NULLs versus strings vazias no nível do BD, você deve pensar nos seus outros tipos de dados. Você armazenaria a data mínima quando nenhuma data é fornecida? ou -1 quando nenhum int é fornecido? Armazenar um valor quando você não tem nenhum valor significa que você deve manter um controle de todo um intervalo de valores diferentes. Pelo menos um para cada tipo de dados (possivelmente mais como você obtém casos em que -1 é um valor real, então você precisa ter alguma alternativa, etc.). Se você precisa / quer fazer algo "fudgy" no nível do aplicativo, isso é uma coisa, mas não há necessidade de poluir seus dados.

    
por 08.08.2012 / 11:18
fonte
4

Infelizmente, o Oracle confundiu a representação da string VARCHAR do tamanho zero com a representação de NULL. Ambos são representados internamente por um único byte com valor zero. Isso torna a discussão muito mais difícil.

Grande parte da confusão em torno do NULL gira em torno de lógica de três valores . Considere o seguinte pseudocódigo:

if ZIPCODE = NULL
    print "ZIPCODE is NULL"
else if ZIPCODE <> NULL
    print "ZIPCODE is not NULL"
else print "Something unknown has happened"

Você não esperaria a terceira mensagem, mas é isso que você obteria, sob três valiosas lógicas. Três valiosas lógicas levam as pessoas a inúmeros erros.

Outra fonte de confusão é tirar inferências da ausência de dados, como desenhar uma inferência do cão que não latiu à noite. Muitas vezes, essas inferências não eram o que o escritor do NULL pretendia veicular.

Tendo dito isso, há muitas situações em que o NULL manipula a ausência de dados muito bem e produz exatamente os resultados desejados. Um exemplo é chaves estrangeiras em relacionamentos opcionais. Se você usar um NULL para indicar nenhum relacionamento em uma determinada linha, essa linha sairá de uma junção interna, exatamente como seria de esperar.

Além disso, esteja ciente de que, mesmo que você evite NULLS completamente nos dados armazenados (sexta forma normal), se fizer alguma junção externa, ainda terá que lidar com NULLS.

    
por 18.03.2011 / 05:16
fonte
3

para a questão técnica específica, o problema não é nulo vs cadeia vazia, é uma falha de validação . Uma string vazia não é um endereço de email válido!

para a questão filosófica, a resposta é similar: valide suas entradas. Se uma string vazia for um valor válido para o campo em questão, espere-o e codifique-o; se não, use null.

Uma string vazia seria uma entrada válida para responder a pergunta: O que o mimo disse à girafa?

    
por 30.12.2010 / 15:49
fonte
2

Eu poderia pensar em um motivo para ter NULL e a string vazia:

  • Você tem endereços de e-mail válidos: [email protected]
  • Você não tem nenhum (e provavelmente deve pedir um): NULL
  • Você sabe que essa pessoa não tem um endereço de e-mail: Empty String.

No entanto, eu não recomendaria isso e usaria um campo separado para saber se você sabe se não existe nenhum.

    
por 15.01.2013 / 16:43
fonte
1

A pergunta que eu entendo, é quais interpretações de NULL e string vazia devem ser escolhidas. Isso depende de quantos estados o campo particular pode estar.

A interpretação depende de como o banco de dados está sendo acessado. Se houver uma camada no código que abstraia completamente o banco de dados, então escolher qualquer política (incluindo dois coulmn) que funcione é completamente aceitável. (Documentar claramente a política é importante, no entanto). No entanto, se o banco de dados está sendo acessado em vários lugares, você deve usar um esquema muito simples, pois o código será mais difícil de manter e pode estar errado neste caso.

    
por 30.12.2010 / 14:05
fonte
1

Bem, basicamente, no nível lógico, não há diferença entre o valor "inválido" e "nenhuma entrada do usuário", eles são apenas todos os "casos especiais" na maioria das vezes. Caso de erro.

Ter nulo leva espaço adicional: ceil (columns_with_null / 8) em bytes / por linha.

Célula vazia e null são ambas as formas de marcar algo errado / deve ser padrão. Por que você precisaria de dois estados "errados"? Por que usar NULLs se eles ocupam espaço adicional e significam exatamente o mesmo que strings vazias? Isso apenas introduzirá confusão e redundância quando você tiver duas coisas significando (isso pode significar) exatamente o mesmo, é fácil esquecer que você deve usar NULLs ao invés de strings vazias (se, por exemplo, o usuário omitir alguns campos).

E seus dados podem se tornar uma bagunça. Em um mundo perfeito você diria "os dados estarão sempre corretos e eu me lembrarei" ... mas quando as pessoas têm que trabalhar em equipe e nem todo mundo está exatamente no seu nível, não é incomum ver ONDE (aa. xx < > '' E bb.zz NÃO É NULO)

Então, ao invés de corrigir os membros da minha equipe todos os dias, eu apenas aplico uma regra simples. Nenhum valor nulo, NUNCA!

A contagem de valores NON-NULL é mais rápida ... pergunta simples é o que você precisa fazer para isso?

    
por 30.12.2010 / 15:35
fonte
1

Eu costumo ver isso não da perspectiva do banco de dados, mas de uma perspectiva de programa. Eu sei que esta questão é para o clique do SQL, mas realmente, quantos usuários acessam dados diretamente por mais tempo?

Em um programa não gosto de null / nothing. Existem algumas exceções, mas são apenas isso. E essas exceções são apenas implementações ruins.

Portanto, se o usuário não inseriu o email, deve haver algo que determine se isso é válido ou não. Se um email em branco está bem, então ele exibe uma string em branco. Se o usuário não colocou um e-mail e isso viola uma regra, o objeto deve indicar isso.

A idéia de ter significado nulo é antiga e é algo que os programadores modernos precisam resolver.

Mesmo no design do DB, por que o campo de e-mail não pode permitir nulos e ter uma cadeia de comprimento zero e ter outro campo indicando se o usuário insere alguma coisa? É um pouco demais para pedir um DBMS? O DB não deve, na minha opinião, lidar com a lógica de negócios nem com a lógica de exibição. Não foi construído para isso e, portanto, faz um trabalho muito ruim de lidar com isso.

    
por 18.03.2011 / 05:48
fonte
-1

Eu não acho que isso importe muito, mas eu gosto mais quando o NULL está lá.

Quando visualizo os dados exibidos em uma tabela (como no SQL Server Management Studio), posso distinguir melhor um valor ausente se ele diz NULL e o segundo plano é de cor diferente.

Se eu vir um espaço em branco, sempre estou me perguntando se está realmente vazio ou se há algum espaço em branco ou alguns caracteres invisíveis. Com NULL é garantido vazio à primeira vista.

Eu normalmente não distingo os valores no aplicativo, porque é inesperado e estranho que NULL e string vazia signifiquem algo diferente. E na maioria das vezes, eu tomo uma abordagem defensiva e apenas luto com os dois estados. Mas para mim como humano, o NULL é mais fácil de processar quando se olha para os dados.

    
por 11.08.2016 / 16:54
fonte