Por que NOT IN com um conjunto contendo NULL sempre retorna FALSE / NULL?

21

Eu tive uma consulta (para Postgres e Informix) com uma NOT INcláusula contendo uma subconsulta que, em alguns casos, retornava NULLvalores, fazendo com que a cláusula (e toda a consulta) falhasse ao retornar qualquer coisa.

Qual é a melhor maneira de entender isso? Eu pensei que era NULLalgo sem valor e, portanto, não esperava que a consulta falhasse, mas obviamente essa não é a maneira correta de pensar NULL.

newenglander
fonte

Respostas:

29

Lógica booleana - ou lógica com três valores

  • IN é uma abreviação de uma série de condições OR
  • x NOT IN (1, 2, NULL) é o mesmo que NOT (x = 1 OR x = 2 OR x = NULL)
  • ... é o mesmo que x <> 1 AND x <> 2 AND x <> NULL
  • ... é o mesmo que true AND true AND unknown**
  • ... = unknown**
  • ... que é quase o mesmo que falseneste caso, pois não passará a WHEREcondição **

Agora, é por isso que as pessoas usam EXISTS+ em NOT EXISTSvez de IN+ NOT IN. Consulte também O uso da lógica NOT em relação aos índices para obter mais

** Nota: unknowné o mesmo que falseno final de uma expressão em uma WHEREcondição.
Enquanto a expressão está sendo avaliada, é desconhecido.
Veja o comentário de @ kgrittn abaixo para saber por que

gbn
fonte
10
Mesmo com o esclarecimento, é tecnicamente errado e de uma maneira que pode queimar alguém. Por exemplo, se você acha que está x <> NULLresolvendo FALSE, você NOT (x <> NULL)deve avaliar TRUE, e não. Ambos avaliam a UNKNOWN. O truque é que uma linha é selecionada apenas se a WHEREcláusula (se presente) for avaliada como TRUE- uma linha será omitida se a cláusula for avaliada como FALSEou UNKNOWN. Esse comportamento (em geral, e para o NOT INpredicado em particular) é obrigatório pelo padrão SQL.
Kgrittn
Também NULL NOT IN (some_subquery)não deve retornar a linha externa, exceto se some_subquerynão retornar nenhuma linha. É por isso que o plano de execução, quando ambas as colunas são capazes de nulo, pode ser consideravelmente mais caro. Exemplo do SQL Server
Martin Smith