Dlaczego NOT IN z zestawem zawierającym NULL zawsze zwraca FALSE / NULL?

21

Miałem zapytanie (dla Postgres i Informix) z NOT INklauzulą ​​zawierającą podzapytanie, które w niektórych przypadkach zwracało NULLwartości, powodując, że ta klauzula (i całe zapytanie) niczego nie zwróciła.

Jak najlepiej to zrozumieć? Myślałem o NULLczymś bez wartości i dlatego nie spodziewałem się, że zapytanie zakończy się niepowodzeniem, ale oczywiście nie jest to właściwy sposób myślenia NULL.

Newenglander
źródło

Odpowiedzi:

29

Logika boolowska - lub logika trójwartościowa

  • IN jest skrótem dla szeregu warunków OR
  • x NOT IN (1, 2, NULL) jest taki sam jak NOT (x = 1 OR x = 2 OR x = NULL)
  • ... jest taki sam jak x <> 1 AND x <> 2 AND x <> NULL
  • ... jest taki sam jak true AND true AND unknown**
  • ... = unknown**
  • ... co jest prawie takie samo jak falsew tym przypadku, ponieważ nie spełni WHEREwarunku **

Teraz, to dlaczego użycie ludowa EXISTS+ NOT EXISTSzamiast IN+ NOT IN. Zobacz także Korzystanie z logiki NOT w stosunku do indeksów, aby uzyskać więcej

** Uwaga: unknownjest taki sam jak falsena końcu wyrażenia w WHEREwarunku.
Podczas oceny wyrażenia nie jest znane.
Zobacz komentarz @ kgrittn poniżej, aby dowiedzieć się, dlaczego

gbn
źródło
10
Nawet z wyjaśnieniem jest to technicznie niepoprawne iw sposób, który mógłby kogoś poparzyć. Na przykład, jeśli zobaczyć x <> NULLjak postanawiając FALSE, można się spodziewać NOT (x <> NULL), aby ocenić na TRUE, a tak nie jest. Obaj oceniają na UNKNOWN. Sztuczka polega na tym, że wiersz jest wybierany tylko wtedy, gdy WHEREklauzula (jeśli jest obecna) ocenia na TRUE- wiersz jest pomijany, jeśli klauzula ocenia na jeden FALSElub UNKNOWN. To zachowanie (ogólnie, a NOT INzwłaszcza predykat) jest wymagane przez standard SQL.
kgrittn
Nie NULL NOT IN (some_subquery)powinien również zwracać zewnętrznego wiersza, chyba że some_subquerynie zwróci żadnych wierszy. Dlatego plan wykonania, gdy obie kolumny mają wartość Null, może być znacznie droższy. Przykład serwera SQL
Martin Smith,