Alguém poderia explicar o seguinte comportamento no SQL?
SELECT * FROM MyTable WHERE MyColumn != NULL (0 Results)
SELECT * FROM MyTable WHERE MyColumn <> NULL (0 Results)
SELECT * FROM MyTable WHERE MyColumn IS NOT NULL (568 Results)
Alguém poderia explicar o seguinte comportamento no SQL?
SELECT * FROM MyTable WHERE MyColumn != NULL (0 Results)
SELECT * FROM MyTable WHERE MyColumn <> NULL (0 Results)
SELECT * FROM MyTable WHERE MyColumn IS NOT NULL (568 Results)
Respostas:
<>
é o padrão SQL-92; !=
é o seu equivalente. Ambos avaliam valores, o que NULL
não é - NULL
é um espaço reservado para dizer que há ausência de valor.
É por isso que você só pode usar IS NULL
/ IS NOT NULL
como predicado para essas situações.
Esse comportamento não é específico para o SQL Server. Todos os dialetos SQL compatíveis com os padrões funcionam da mesma maneira.
Nota : Para comparar se seu valor não é nulo , use IS NOT NULL
, enquanto para comparar com valor não nulo , use <> 'YOUR_VALUE'
. Não posso dizer se meu valor é igual ou não a NULL, mas posso dizer se meu valor é NULL ou NOT NULL. Posso comparar se meu valor é algo diferente de NULL.
!=
até ~ 9i, pelo que entendi, o que trouxe muita sintaxe ANSI-92. Minha crença é que o MySQL é semelhante, iniciando o suporte na versão 4.x.
!=
poderia ter sido incluído em uma especificação posterior como uma alternativa a <>
. Não tenho minhas mãos em novas especificações, então não posso dizer com certeza.
WHERE MyColumn != NULL
ou WHERE MyColumn = NULL
determinista? Ou, em outras palavras, é garantido o retorno sempre de 0 linhas, independentemente de MyColumn
ser nulo no banco de dados ou não?
!=
apenas avalia valores, fazer algo como WHERE MyColumn != 'somevalue'
não retornará os registros NULL.
NULL não tem valor e, portanto, não pode ser comparado usando os operadores de valor escalar.
Em outras palavras, nenhum valor pode ser igual a (ou não) NULL porque NULL não tem valor.
Portanto, o SQL possui predicados especiais IS NULL e IS NOT NULL para lidar com NULL.
'a' != null
NÃO devolver um valor ( true
/ 1
) é contra-intuitivo e me pega de vez em quando! Eu teria pensado que "algum valor comparado a nenhum valor" sempre seria "não igual", mas talvez seja apenas eu?!?
SELECT * FROM MyTable WHERE coalesce(MyColumn, 'x') <> 'x'
atribuir uma constante se for um valor NULL, desde que você forneça um tipo de dados apropriado para o valor sentinela x (nesse caso, uma string / char). Essa é a sintaxe do TSQL, mas o Oracle e outros mecanismos têm recursos semelhantes.
Observe que esse comportamento é o comportamento padrão (ANSI).
Se vocês:
SET ANSI_NULLS OFF
http://msdn.microsoft.com/en-us/library/ms188048.aspx
Você obterá resultados diferentes.
SET ANSI_NULLS OFF
aparentemente vai desaparecer no futuro ...
create unique index UK_MyTable on MyTable (Column) where Column is not null
): msdn.microsoft.com/en-us/library/cc280372.aspx
SET ANSI_NULLS
está DESATIVADO, os operadores de comparação Igual a (=) e Diferente de (<>) não seguem o padrão ISO. Uma instrução SELECT que usa WHERE column_name = NULL
retorna as linhas que possuem valores nulos em column_name. Uma instrução SELECT que usa WHERE column_name <> NULL
retorna as linhas que possuem valores não nulos na coluna. Além disso, uma instrução SELECT que usa WHERE column_name <> XYZ_value
retorna todas as linhas que não são XYZ_value e que não são NULL. IMHO, esta última afirmação parece um pouco estranha na exclusão de valores nulos dos resultados!
No SQL, qualquer coisa que você avalie / calcule com NULL
resultados em DESCONHECIDO
É por isso que SELECT * FROM MyTable WHERE MyColumn != NULL
ou SELECT * FROM MyTable WHERE MyColumn <> NULL
fornece 0 resultados.
Para fornecer uma verificação de NULL
valores, a função isNull é fornecida.
Além disso, você pode usar o IS
operador como usou na terceira consulta.
Espero que isto ajude.
O único teste para NULL é IS NULL ou NOT NULL. Testar a igualdade não faz sentido, porque, por definição, não se sabe qual é o valor.
Aqui está um artigo da Wikipedia para ler:
Nós usamos
SELECT * FROM MyTable WHERE ISNULL(MyColumn, ' ') = ' ';
para retornar todas as linhas em que MyColumn é NULL ou todas as linhas em que MyColumn é uma sequência vazia. Para muitos "usuários finais", o problema de seqüência de caracteres NULL vs. vazio é uma distinção sem necessidade e ponto de confusão.
Eu simplesmente não vejo a razão funcional e perfeita para que os nulos não sejam comparáveis a outros valores ou outros nulos, porque podemos compará-lo claramente e dizer que eles são iguais ou não em nosso contexto. É engraçado. Só por causa de algumas conclusões lógicas e consistência, precisamos nos preocupar constantemente com isso. Não é funcional, torne-o mais funcional e deixe que filósofos e cientistas concluam se é consistente ou não e mantém a "lógica universal". :) Alguém pode dizer que é por causa de índices ou qualquer outra coisa, duvido que essas coisas não pudessem ser feitas para suportar nulos iguais aos valores. É o mesmo que comparar dois copos vazios, um é copo de vinho e outro é copo de cerveja; não estamos comparando os tipos de objetos, mas os valores que eles contêm, o mesmo que você pode comparar int e varchar, com nulo ' é ainda mais fácil, não é nada e o que dois nada têm em comum, eles são os mesmos, claramente comparáveis por mim e por todos os outros que escrevem sql, porque estamos constantemente quebrando essa lógica, comparando-os de maneiras estranhas por causa de alguns padrões ANSI. Por que não usar a energia do computador para fazer isso por nós e duvido que isso acelere as coisas se tudo relacionado for construído com isso em mente. "Não é nulo, não é nada", não é maçã, é apfel, vamos lá ... Funcionalmente é seu amigo e também há lógica aqui. No final, a única coisa que importa é a funcionalidade e o uso de nulos dessa maneira traz mais ou menos funcionalidade e facilidade de uso. É mais útil? porque estamos constantemente quebrando essa lógica, comparando-os de maneiras estranhas por causa de alguns padrões ANSI. Por que não usar a energia do computador para fazer isso por nós e duvido que isso acelere as coisas se tudo relacionado for construído com isso em mente. "Não é nulo, não é nada", não é maçã, é apfel, vamos lá ... Funcionalmente é seu amigo e também há lógica aqui. No final, a única coisa que importa é a funcionalidade e o uso de nulos dessa maneira traz mais ou menos funcionalidade e facilidade de uso. É mais útil? porque estamos constantemente quebrando essa lógica, comparando-os de maneiras estranhas por causa de alguns padrões ANSI. Por que não usar a energia do computador para fazer isso por nós e duvido que isso acelere as coisas se tudo relacionado for construído com isso em mente. "Não é nulo, não é nada", não é maçã, é apfel, vamos lá ... Funcionalmente é seu amigo e também há lógica aqui. No final, a única coisa que importa é a funcionalidade e o uso de nulos dessa maneira traz mais ou menos funcionalidade e facilidade de uso. É mais útil? s não maçã é apfel, vamos lá ... Funcionalmente é seu amigo e também há lógica aqui. No final, a única coisa que importa é a funcionalidade e o uso de nulos dessa maneira traz mais ou menos funcionalidade e facilidade de uso. É mais útil? s não maçã é apfel, vamos lá ... Funcionalmente é seu amigo e também há lógica aqui. No final, a única coisa que importa é a funcionalidade e o uso de nulos dessa maneira traz mais ou menos funcionalidade e facilidade de uso. É mais útil?
Considere este código:
SELECT CASE WHEN NOT (1 = null or (1 is null and null is null)) THEN 1 ELSE 0 end
Quantos de vocês sabem o que esse código retornará? Com ou sem NÃO, retorna 0. Para mim, isso não é funcional e é confuso. No c #, tudo é como deveria ser, as operações de comparação retornam valor, logicamente isso também produz valor, porque, se isso não acontecesse, não havia nada para comparar (exceto nada :):). Eles apenas "disseram": qualquer coisa comparada com "retornos" nulos 0 e que cria muitas soluções alternativas e dores de cabeça.
Este é o código que me trouxe aqui:
where a != b OR (a is null and b IS not null) OR (a IS not null and b IS null)
Eu só preciso comparar se dois campos (em onde) têm valores diferentes, eu poderia usar a função, mas ...
NULL Não pode ser comparado a nenhum valor usando os operadores de comparação. NULL = NULL é falso. Nulo não é um valor. O operador IS é especialmente projetado para lidar com comparações NULL.
null = null
onde alguém pode usar 1=0
em alguma consulta ad-hoc. E se eles se queixam, eu mudar para null != null
:)
Pergunta antiga, mas o seguinte pode oferecer mais detalhes.
null
representa nenhum valor ou um valor desconhecido. Não especifica por que não há valor, o que pode levar a alguma ambiguidade.
Suponha que você execute uma consulta como esta:
SELECT *
FROM orders
WHERE delivered=ordered;
isto é, você está procurando linhas nas quais as datas ordered
e delivered
são iguais.
O que é esperado quando uma ou ambas as colunas são nulas?
Como pelo menos uma das datas é desconhecida, você não pode esperar dizer que as duas datas são iguais. Este também é o caso quando as duas datas são desconhecidas: como podem ser as mesmas se nem sabemos o que são?
Por esse motivo, qualquer expressão que trate null
como um valor deve falhar. Nesse caso, não corresponderá. Este também é o caso se você tentar o seguinte:
SELECT *
FROM orders
WHERE delivered<>ordered;
Novamente, como podemos dizer que dois valores não são os mesmos se não sabemos o que são.
SQL tem um teste específico para valores ausentes:
IS NULL
Especificamente, não está comparando valores, mas procura valores ausentes .
Finalmente, no que diz respeito ao !=
operador, tanto quanto sei, ele não está de fato em nenhuma das normas, mas é amplamente suportado. Foi adicionado para fazer com que programadores de alguns idiomas se sintam mais à vontade. Francamente, se um programador tem dificuldade em lembrar qual idioma está usando, ele começa mal.
NULL
queremos dizer que estamos comparando um valor a 'ter um NULL
valor', não o valor ao "valor indeterminado que o subjacente NULL
está tendo? mas que não sabemos ", que obviamente não poderemos saber. Isso realmente facilitaria as coisas.
IS NULL
seja muito mais árduo do que escrever = NULL
. Eu acho que seria mais consistente se WHERE columnA = columnB
tivesse a mesma interpretação que WHERE columnA = NULL
, em vez de tratar a última como um caso especial. Lembre-se que nãoNULL
é um valor. Nas linguagens de programação em que é legítimo testá- lo, é porque tem um significado diferente; não representa algo desconhecido, mas uma redefinição deliberada de um valor. Não é assim com o SQL. variable == null
null
IS NULL
AND =NULL
no seu exemplo mais recente. Mas dê uma olhada no último de Hover. Estou cansado de experimentar isso de novo e de novo, tendo que fazer muitas coisas desnecessárias? verificação extra ...
Gostaria de sugerir esse código que fiz para descobrir se há uma alteração em um valor,
i
sendo o novo valor e d
o antigo (embora a ordem não importe). Nesse caso, uma mudança de valor para nulo ou vice-versa é uma mudança, mas de nulo para nulo não é (é claro, de valor para outro valor é uma mudança, mas de valor para o mesmo não é).
CREATE FUNCTION [dbo].[ufn_equal_with_nulls]
(
@i sql_variant,
@d sql_variant
)
RETURNS bit
AS
BEGIN
DECLARE @in bit = 0, @dn bit = 0
if @i is null set @in = 1
if @d is null set @dn = 1
if @in <> @dn
return 0
if @in = 1 and @dn = 1
return 1
if @in = 0 and @dn = 0 and @i = @d
return 1
return 0
END
Para usar esta função, você pode
declare @tmp table (a int, b int)
insert into @tmp values
(1,1),
(1,2),
(1,null),
(null,1),
(null,null)
---- in select ----
select *, [dbo].[ufn_equal_with_nulls](a,b) as [=] from @tmp
---- where equal ----
select *,'equal' as [Predicate] from @tmp where [dbo].[ufn_equal_with_nulls](a,b) = 1
---- where not equal ----
select *,'not equal' as [Predicate] from @tmp where [dbo].[ufn_equal_with_nulls](a,b) = 0
Os resultados são:
---- in select ----
a b =
1 1 1
1 2 0
1 NULL 0
NULL 1 0
NULL NULL 1
---- where equal ----
1 1 equal
NULL NULL equal
---- where not equal ----
1 2 not equal
1 NULL not equal
NULL 1 not equal
O uso de sql_variant o torna compatível com vários tipos
NULL não é nada ... é desconhecido. NULL não é igual a nada. É por isso que você precisa usar a frase mágica IS NULL em vez de = NULL nas suas consultas SQL
Você pode consultar isso: http://weblogs.sqlteam.com/markc/archive/2009/06/08/60929.aspx
<>
que está no 92 especificação, mas a maioria dos fornecedores de suporte!=
e / ou está incluída em uma especificação mais tarde como 99 ou 03.