No SQL server, se você tiver nullParam=NULL
uma cláusula where, ela sempre será avaliada como falsa. Isso é contra-intuitivo e me causou muitos erros. Entendo que as palavras IS NULL
- IS NOT NULL
chave e são a maneira correta de fazer isso. Mas por que o SQL Server se comporta dessa maneira?
sql
sql-server
null
Byron Whitlock
fonte
fonte
Respostas:
Pense no nulo como "desconhecido" nesse caso (ou "não existe"). Em qualquer um desses casos, você não pode dizer que eles são iguais, porque você não conhece o valor de nenhum deles. Portanto, null = null avalia como não verdadeiro (falso ou nulo, dependendo do seu sistema), porque você não conhece os valores para dizer que eles são iguais. Esse comportamento é definido no padrão ANSI SQL-92.
EDIT: Isso depende da sua configuração ansi_nulls . se você tiver ANSI_NULLS desativado, isso será avaliado como verdadeiro. Execute o seguinte código para um exemplo ...
fonte
(NaN == NaN) == false && (NaN != Nan) == false && (NaN < NaN) == false && ...
- porque, bem, se não é um número, você simplesmente não pode dizer muito sobre isso; é algo desconhecido. O conceito é sólido, mesmo que não seja intuitivo para pessoas que nunca o viram antes.NULL
as expressões SQL podem ser tratadas como uma variável matemática distinta . Portanto, uma expressãoNULL = NULL
deve ser tratada comox = y
, ondex
ey
são variáveis não acopladas. Agora, se alguém lhe perguntar, qual é o valorx = y
? A única resposta razoável é "algunsz
". Então nós temos(x = y) = z
- ou, transcrevendo de volta para o SQL(NULL = NULL) = NULL
,.Quantos anos Frank tem? Eu não sei (nulo).
Quantos anos tem Shirley? Eu não sei (nulo).
Frank e Shirley têm a mesma idade?
A resposta correta deve ser "não sei" (nulo), não "não", como Frank e Shirley podem ter a mesma idade, simplesmente não sabemos.
fonte
null = null
produzFALSE
, nãoNULL
.Espero esclarecer aqui minha posição.
Essa
NULL = NULL
avaliaçãoFALSE
está errada. Hacker e Mister responderam corretamenteNULL
. Aqui está o porquê. Dewayne Christensen escreveu para mim, em um comentário para Scott Ivey :Eles podem ser diferentes ou iguais, você não sabe até que um abra os dois presentes. Quem sabe? Você convidou duas pessoas que não se conhecem e ambos têm feito para você o mesmo dom - raro, mas não impossível § .
Portanto, a pergunta: esses dois DESCONHECIDOS apresentam o mesmo (igual, =)? A resposta correta é: DESCONHECIDO (ie
NULL
).Este exemplo teve como objetivo demonstrar que ".. (
false
ounull
, dependendo do seu sistema) .." é uma resposta correta - não é, apenasNULL
é correta em 3VL (ou é aceitável que você aceite um sistema que fornece respostas erradas? )Uma resposta correta para esta pergunta deve enfatizar esses dois pontos:
Por isso, reitero: o SQL não ajuda em nada a interpretar a propriedade reflexiva da igualdade, que afirma que:
.. num 3VL (
TRUE
,FALSE
,NULL
). A expectativa das pessoas estaria de acordo com 2VL (TRUE
,FALSE
que mesmo em SQL é válida para todos os outros valores), ou seja,x = x
sempre avaliar aTRUE
, para qualquer valor possível de x - sem exceções.Observe também que os NULLs são " não valores " válidos (como seus apologistas pretendem que sejam) que podem ser atribuídos como valores de atributo (??) como parte das variáveis de relação. Portanto, eles são valores aceitáveis de todos os tipos (domínio), não apenas do tipo de expressões lógicas.
E esse foi o meu argumento :
NULL
como valor, é uma "besta estranha". Sem eufemismo, prefiro dizer: bobagem .Eu acho que essa formulação é muito mais clara e menos discutível - desculpe pela minha baixa proficiência em inglês.
Este é apenas um dos problemas dos NULLs. Melhor evitá-los completamente, quando possível.
§ estamos preocupados com os valores aqui; portanto, o fato de os dois presentes serem sempre dois objetos físicos diferentes não é uma objeção válida; se você não está convencido, desculpe, não é este o lugar para explicar a diferença entre semântica de valor e de "objeto" (a Álgebra Relacional tem semântica de valor desde o início - consulte o princípio da informação do Codd; acho que alguns implementadores do SQL DBMS não nem se importa com uma semântica comum).
§§ que eu saiba, esse é um axioma aceito (de uma forma ou de outra, mas sempre interpretado em uma 2VL) desde a antiguidade e exatamente por ser tão intuitivo. 3VLs (é uma família de lógicas na realidade) é um desenvolvimento muito mais recente (mas não tenho certeza de quando foi desenvolvido).
Nota lateral: se alguém introduzir os tipos Bottom , Unit e Option como tentativas de justificar SQL NULLs, ficarei convencido apenas após um exame bastante detalhado que mostrará como as implementações SQL com NULLs têm um sistema de tipo de som e esclarecerá, finalmente, o que realmente são NULLs (esses "valores-não-valores-iguais").
A seguir, citarei alguns autores. Qualquer erro ou omissão é provavelmente meu e não dos autores originais.
Joe Celko em SQL NULLs
Eu vejo Joe Celko frequentemente citado neste fórum. Aparentemente, ele é um autor muito respeitado aqui. Então, eu disse a mim mesmo: "o que ele escreveu sobre SQL NULLs? Como ele explica vários problemas com NULLs?". Um amigo meu tem uma versão eletrônica do SQL for smarties de Joe Celko: programação SQL avançada, 3ª edição . Vamos ver.
Primeiro, o sumário. O que mais me impressiona é o número de vezes que NULL é mencionado e nos mais variados contextos:
e assim por diante. Soa "um caso especial desagradável" para mim.
Vou abordar alguns desses casos com trechos deste livro, tentando me limitar ao essencial, por razões de direitos autorais. Acho que essas citações se enquadram na doutrina do "uso justo" e podem até estimular a compra do livro - por isso espero que ninguém reclame (caso contrário, precisarei excluir a maior parte, se não todas). Além disso, evitarei relatar trechos de código pelo mesmo motivo. Me desculpe por isso. Compre o livro para ler sobre o raciocínio com dados.
Números de página entre parênteses a seguir.
Mais uma vez, esse absurdo de "valor, mas não exatamente um valor". O resto parece bastante sensato para mim.
A propósito de SQL, NULLs e infinito:
Implementações de SQL indecisas sobre o que NULL realmente significa em contextos específicos:
Joe Celko citando David McGoveran e CJ Date:
Nulos como um vício em drogas :
Minha objeção exclusiva aqui é "usá-los adequadamente", que interage mal com comportamentos de implementação específicos.
(separador)
Mas UNKNOWN é uma fonte de problemas em si, de modo que CJ Date, em seu livro citado abaixo, é recomendado no capítulo 4.5. Evitando nulos no SQL :
Leia "ASIDE" em DESCONHECIDO, também linkado abaixo.
(separador)
Objeção: NULLs confunde até pessoas que conhecem bem o SQL, veja abaixo.
(separador)
(separador)
(separador)
(separador)
(separador)
(separador)
Discutindo GROUP BY:
Isso significa que para a cláusula GROUP BY NULL = NULL não é avaliado como NULL, como em 3VL, mas é avaliado como TRUE.
O padrão SQL é confuso:
E assim por diante. Eu acho que é o suficiente por Celko.
Data CJ em SQL NULLs
A data CJ é mais radical quanto aos NULLs: evite NULLs no SQL, ponto final. De fato, o capítulo 4 de sua SQL e a teoria relacional: Como escrever um código SQL preciso é intitulado "SEM DUPLICADOS, SEM NULOS", com os subcapítulos "4.4 O que há de errado com os nulos?" e "4.5 Evitando nulos no SQL" (siga o link: graças ao Google Livros, você pode ler algumas páginas on-line).
Fabian Pascal em SQL NULLs
De suas questões práticas no gerenciamento de banco de dados - uma referência para o profissional que pensa (sem trechos on-line, desculpe):
fonte
NULL
não é um valor.(NULL = NULL) -> FALSE
. Para citar a documentação deANSI_NULLS
: "Quando ON é especificado, todas as comparações com um valor nulo são avaliadas como DESCONHECIDAS . Quando OFF é especificado, comparações de valores não-UNICODE com um valor nulo são avaliadas como TRUE se ambos os valores forem NULL."Talvez isso dependa, mas pensei que
NULL=NULL
avaliaNULL
como a maioria das operações com NULL como um operando.fonte
Só porque você não sabe o que são duas coisas, não significa que são iguais. Se, quando você pensa em
NULL
você, pensa em "NULL" (string), provavelmente deseja um teste de igualdade diferente como oIS DISTINCT FROM
AND do PostgresqlIS NOT DISTINCT FROM
Dos documentos do PostgreSQL sobre "Funções e operadores de comparação"
fonte
O conceito de NULL é questionável, para dizer o mínimo. Codd introduziu o modelo relacional e o conceito de NULL em contexto (e propôs mais de um tipo de NULL!) No entanto, a teoria relacional evoluiu desde os escritos originais de Codd: algumas de suas propostas foram descartadas (por exemplo, chave primária) e outros nunca pegaram (por exemplo, operadores teta). Na teoria relacional moderna (teoria verdadeiramente relacional, devo enfatizar) NULL simplesmente não existe. Veja O Terceiro Manifesto. http://www.thethirdmanifesto.com/
A linguagem SQL sofre o problema de compatibilidade com versões anteriores. O NULL chegou ao SQL e estamos presos a ele. Indiscutivelmente, a implementação do
NULL
SQL é falha (a implementação do SQL Server torna as coisas ainda mais complicadas devido à suaANSI_NULLS
opção).Eu recomendo evitar o uso de colunas NULLable nas tabelas base.
Embora talvez eu não deva ficar tentado, eu só queria afirmar uma correção minha sobre como
NULL
funciona o SQL:NULL
=NULL
avalia comoUNKNOWN
.UNKNOWN
é um valor lógico.NULL
é um valor de dados.É fácil provar, por exemplo
SELECT NULL = NULL
gera corretamente um erro no SQL Server. Se o resultado fosse um valor de dados, esperamos ver
NULL
, como algumas respostas aqui (erradamente) sugerem que sim.O valor lógico
UNKNOWN
é tratado de maneira diferente no SQL DML e no SQL DDL, respectivamente.No SQL DML,
UNKNOWN
faz com que as linhas sejam removidas do conjunto de resultados.Por exemplo:
O
INSERT
êxito desta linha, mesmo que aCHECK
condição seja resolvidaNULL = NULL
. Isso ocorre devido ao padrão SQL-92 ("ANSI"):Leia isso novamente com atenção, seguindo a lógica.
Em inglês simples, nossa nova linha acima recebe o 'benefício da dúvida' sobre ser
UNKNOWN
e permissão para passar.No SQL DML, a regra para a
WHERE
cláusula é muito mais fácil de seguir:Em inglês simples, as linhas avaliadas
UNKNOWN
são removidas do conjunto de resultados.fonte
No technet, há uma boa explicação de como os valores nulos funcionam.
Nulo significa desconhecido.
Portanto, a expressão booleana
valor = nulo
não avalia como falso, avalia como nulo, mas se esse for o resultado final de uma cláusula where, nada será retornado. Essa é uma maneira prática de fazer isso, pois retornar nulo seria difícil de conceber.
É interessante e muito importante entender o seguinte:
Se em uma consulta tivermos
e
então
"value = @ param" avalia como nulo
"@param é nulo" avalia como true
"id = @ anotherParam" avalia como true
Portanto, a expressão a ser avaliada se torna
(nulo ou verdadeiro) e verdadeiro
Podemos ficar tentados a pensar que aqui "null Or true" será avaliado como null e, portanto, toda a expressão se tornará nula e a linha não será retornada.
Isto não é verdade. Por quê?
Como "null Or true" é avaliado como true, o que é muito lógico, pois se um operando for verdadeiro com o operador Or, não importa o valor do outro operando, a operação retornará true. Portanto, não importa que o outro operando seja desconhecido (nulo).
Finalmente, temos true = true e, portanto, a linha será retornada.
Nota: com a mesma lógica clara que "null Or true" avalia como true, "null And true" avalia como null.
Atualização:
Ok, apenas para completar, quero adicionar o restante aqui também, o que resulta bastante divertido em relação ao acima.
"nulo ou falso" é avaliado como nulo, "nulo e falso" é avaliado como falso. :)
A lógica ainda é obviamente tão evidente quanto antes.
fonte
Porque
NULL
significa 'valor desconhecido' e dois valores desconhecidos não podem ser iguais.Então, se a nossa lógica
NULL
N ° 1 é igual aNULL
N ° 2, então temos que dizer isso de alguma forma:onde o valor conhecido
-1
N ° 1 é igual a-1
N ° 2fonte
nullParam1 = -1
enullParam2 =NULL
e airplain acidente .... deve serISNULL(NULLIF(@nullParam1, @nullParam2), NULLIF(@nullParam2, nullParam1)) IS NULL
As respostas aqui parecem vir de uma perspectiva de CS, então eu quero adicionar uma da perspectiva de desenvolvedor.
Para um desenvolvedor, NULL é muito útil. As respostas aqui dizem que NULL significa desconhecido, e talvez na teoria do CS seja verdade, não se lembre, já faz um tempo. No desenvolvimento atual, pelo menos na minha experiência, isso acontece cerca de 1% das vezes. Os outros 99% são usados para casos em que o valor não é DESCONHECIDO, mas é sabido que é ausente.
Por exemplo:
Client.LastPurchase
, para um novo cliente. Não é desconhecido, sabe-se que ele ainda não fez uma compra.Ao usar um ORM com um mapeamento Tabela por hierarquia de classes , alguns valores simplesmente não são mapeados para determinadas classes.
Ao mapear uma estrutura de árvore, uma raiz geralmente terá
Parent = NULL
E muitos mais...
Tenho certeza que a maioria dos desenvolvedores, em algum momento
WHERE value = NULL
, escreveu , não obteve nenhum resultado, e foi assim que aprenderam sobreIS NULL
sintaxe. Veja quantos votos essa pergunta e as que têm estão vinculadas.Os bancos de dados SQL são uma ferramenta e devem ser projetados da maneira mais fácil para os usuários entenderem.
fonte
NULL não é igual a nada, nem a si próprio. Minha solução pessoal para entender o comportamento do NULL é evitar usá-lo o máximo possível :).
fonte
A pergunta:
um desconhecido é igual a outro desconhecido?
(NULL = NULL)
Essa pergunta é algo que ninguém pode responder, por padrão, é true ou false dependendo da configuração de ansi_nulls.
No entanto, a pergunta:
essa variável desconhecida é desconhecida?
Esta pergunta é bem diferente e pode ser respondida com verdadeiro.
nullVariable = null está comparando os valores
nullVariable is null está comparando o estado da variável
fonte
A confusão surge do nível de indireção (abstração) resultante do uso de NULL .
Voltando à analogia "o que há sob a árvore de Natal", "Desconhecido" descreve o estado do conhecimento sobre o que está na Caixa A.
Portanto, se você não sabe o que há na Caixa A, diz que é "Desconhecido", mas isso não significa que "Desconhecido" esteja dentro da caixa . Algo diferente de desconhecido está na caixa, possivelmente algum tipo de objeto, ou possivelmente nada está na caixa.
Da mesma forma, se você não souber o que está na Caixa B, poderá rotular seu estado de conhecimento sobre o conteúdo como "Desconhecido".
Então aqui está o kicker: O seu estado de conhecimento sobre Box A é igual ao seu estado de conhecimento sobre Box B . (O seu estado de conhecimento em ambos os casos é "Desconhecido" ou "Não sei o que há na caixa".) Mas o conteúdo das caixas pode ou não ser igual.
Voltando ao SQL, idealmente, você só poderá comparar valores quando souber o que são. Infelizmente, o rótulo que descreve a falta de conhecimento é armazenado na própria célula , por isso somos tentados a usá-lo como um valor. Mas não devemos usar isso como um valor, porque levaria a "o conteúdo da Caixa A é igual ao conteúdo da Caixa B quando não sabemos o que está na Caixa A e / ou não sabemos o que está na Caixa B. (Logicamente, a implicação "se eu não souber o que está na caixa A e se não souber o que está na caixa B, então o que está na caixa A = o que está na caixa B" é falso.)
Yay, cavalo morto.
fonte
O MSDN tem um bom artigo descritivo sobre nulos e a lógica de três estados que eles geram.
Em resumo, a especificação SQL92 define NULL como desconhecido, e NULL usado nos seguintes operadores causa resultados inesperados para os não iniciados:
fonte
null é desconhecido no sql, portanto não podemos esperar que duas incógnitas sejam iguais.
No entanto, você pode obter esse comportamento definindo ANSI_NULLS como Desativado (ativado por padrão). Você poderá usar o operador = para valores nulos.
fonte
null
, aprenda a entendê-lo ou apenas altere a tabela para ter tipos int e atualizar as colunas.Você trabalha para o governo registrando informações sobre os cidadãos. Isso inclui o ID nacional de todas as pessoas no país. Uma criança foi deixada na porta de uma igreja cerca de 40 anos atrás, ninguém sabe quem são seus pais. O ID do pai desta pessoa é
NULL
. Existem duas pessoas assim. Contar pessoas que compartilham o mesmo ID do pai com pelo menos uma outra pessoa (pessoas que são irmãos). Você conta esses dois também?A resposta é não, você não, porque não sabemos se são irmãos ou não.
Suponha que você não tenha uma
NULL
opção e, em vez disso, use algum valor predeterminado para representar “o desconhecido”, talvez uma string vazia ou o número 0 ou um caractere *, etc. Então você teria em suas consultas que * = * , 0 = 0 e “” = “”, etc. Isso não é o que você deseja (como no exemplo acima) e, como muitas vezes você esquece desses casos (o exemplo acima é um caso de franja clara, fora do pensamento cotidiano comum ), você precisa lembrar o idioma queNULL = NULL
não é verdadeiro.Necessidade é a mãe da invenção.
fonte
Apenas uma adição a outras respostas maravilhosas:
fonte
Se você está procurando uma expressão retornando true para dois NULLs, pode usar:
É útil se você deseja replicar dados de uma tabela para outra.
fonte
O teste de igualdade, por exemplo, em uma declaração de caso quando a cláusula, pode ser alterado de
para
Se eu quiser tratar espaços em branco e string vazia como iguais a NULL, geralmente também uso um teste de igualdade como:
fonte