Auto-comparação de valor NULL em uma tabela

13

Estou sempre intrigado com algum comportamento misterioso do t-sql, como o seguinte

-- Create table t and insert values.  
use tempdb
CREATE TABLE dbo.t (a INT NULL);  
-- insert 3 values
INSERT INTO dbo.t values (NULL),(0),(1);  
GO  
set ansi_nulls off -- purposely turn off, so we can allow NULL comparison, such as null = null
go
-- expect 3 rows returned but only 2 returned (without null value row)
select * from dbo.t where a = a 

Não se trata de como recuperar todas as linhas de uma tabela e também de evitar o uso de ANSI_NULLS.

Eu só quero solicitar algumas idéias sobre por que o t-sql se comporta dessa maneira.

jyao
fonte

Respostas:

13

Esse é um comportamento surpreendente, mas, na página do MSDN SET ANSI_NULLS, podemos pelo menos saber que esse é o comportamento esperado. Mais um motivo para nunca usar ANSI_NULLS OFF:

SET ANSI_NULLSafeta uma comparação apenas se um dos operandos da comparação for uma variável que é NULLou uma literal NULL. Se os dois lados da comparação forem colunas ou expressões compostas, a configuração não afetará a comparação.

ypercubeᵀᴹ
fonte
8

Embora possa não estar claro na documentação do msdn, acredito que você encontrará o seguinte

"SET ANSI_NULLS ON afeta uma comparação apenas se um dos operandos da comparação for uma variável NULL ou literal NULL. Se os dois lados da comparação forem colunas ou expressões compostas, a configuração não afetará a comparação."

Consulte este /programming/2866714/how-does-ansi-nulls-work-in-tsql

Scott Hodgin
fonte
Obrigado Scott e ypercube, as duas respostas estão nos pontos corretos para esse comportamento, por isso eu votei nas duas respostas.
precisa saber é
Ypercube foi o primeiro :)
Scott Hodgin
4

Robert Sheldon no post a seguir de 2015 discute comportamentos NULL e por que às vezes (mas nem sempre) falham

https://www.simple-talk.com/sql/t-sql-programming/how-to-get-nulls-horribly-wrong-in-sql-server/

Ele descreve 13 falhas nulas que um programador pode facilmente tropeçar.

Falha nº 1: sem saber o que significa NULL

Explicação: NULL é um valor não existente, um valor inexistente. Não é zero. Não é uma string vazia. Um valor não pode ser igual a NULL. Não há dois valores NULL iguais .

Esse é o problema básico, mas não deixe de ler sobre as outras falhas.

Sim, as versões anteriores (acredito que antes do SQL Server 7) se comportaram de maneira diferente, mais parecidas com o que você deseja.

No entanto, se você procurar o problema no Stack Overflow e no Stack Exchange, encontrará muitos threads longos discutindo os problemas.

RLF
fonte
3
Uma vez, li o post vinculado de Robert Sheldon, mas ele (IMHO) não tem nenhuma teoria ou evidência que explique o comportamento do meu exemplo.
jyao
1
"Não existem dois valores NULL iguais." OK, mas mesmo as pessoas que sabem que esperariam o contrário quando ansi nulls estiver desativado. Especialmente porque o WHERE NULL = NULLrendimento é verdadeiro quando a configuração é de.
precisa saber é o seguinte
1

Para adicionar à discussão, a definição de NULL do padrão SQL92 pode ser interpretada de forma ambígua. Aqui está um bom resumo do manuseio e interpretação de NULL de vários DBMS, cortesia de sqlite.org.

DIVULGAÇÃO : Eu meio que lembro de ler sobre a "ambiguidade" do SQL92 a partir de uma versão mais antiga (há 6 a 8 anos) da página sqlite.org vinculada acima, mas essa página foi atualizada desde então.

A resposta de RLF acima tem uma boa citação, mas se eu não concordar com Robert Sheldon é só porque eu considero "algo que não existe" (ou seja, um NULL ) para ser filosoficamente e Inglês-language-semanticamente equivalente a "alguma coisa outra coisa que não existe " Se eu quiser entender a lógica de Sheldon, pode-se declarar que a definição de NULL também é NULL. (Se não existe, como podemos defini-lo? Assustador, hein?)

Eu vejo uma variação da produção de Russell's Paradox ( e uma dor de cabeça). : - \

Mas, novamente, esta é uma discussão sobre semântica no idioma inglês ( NOT SQL) e o debate sobre filosofia pertence aqui . :-)

pr1268
fonte
PS Eu sou novo aqui nesta comunidade SE; se isso já foi discutido ad nauseum , peço desculpas.
pr1268
1
Onde exatamente está a ambiguidade no padrão?
precisa saber é o seguinte
@ ypercubeᵀᴹ: Eu acredito que a ambiguidade está na tentativa de "encaixar" uma 3VL em um booleano. As junções de tabela com comparações NULL podem ser interpretadas de várias maneiras diferentes.
pr1268
Eu concordaria em inconsistência, mas não em ambiguidade.
precisa saber é o seguinte
1
@ ypercubeᵀᴹ: É justo ... Eu estava apenas citando o que uma versão mais antiga da página sqlite.org vinculei acima disse ("SQL92 é ambíguo no que diz respeito à manipulação e interpretação de NULL" ou algo muito semelhante). Mas não pretendo discutir. Talvez a página sqlite.org tenha sido enganosa e / ou totalmente incorreta. O que provavelmente explica por que foi atualizado.
precisa saber é