2009-12-02 10 views
21

czytałem ten artykuł: Get null == null in SQLdlaczego nie jest zerowy równy null fałszywy

I zgoda, że ​​gdy próbuje przetestować równość między dwoma (pustych) kolumnach SQL, właściwym podejściem jest:

where ((A=B) OR (A IS NULL AND B IS NULL)) 

Gdy A i B mają wartość NULL, (A = B) nadal zwraca FALSE, ponieważ wartość NULL nie jest równa NULL. Dlatego wymagana jest dodatkowa kontrola.

A co z testowaniem nierówności? Wynikające z powyższej dyskusji, to mnie myśleć, że nierówności testowym musiałbym zrobić coś takiego:

WHERE ((A <> B) OR (A IS NOT NULL AND B IS NULL) OR (A IS NULL AND B IS NOT NULL)) 

Jednak zauważyłem, że nie jest konieczne (przynajmniej nie na Informix 11.5), i mogę po prostu wykonaj:

where (A<>B) 

Jeśli A i B mają wartość NULL, to zwraca FALSE. Jeśli NULL nie jest równe NULL, to czy nie powinno to zwracać PRAWDA?

EDIT
Są to dobre odpowiedzi, ale myślę, że moje pytanie było trochę niejasne. Pozwól mi przeformułować:

Zważywszy, że A lub B może być NULL, czy to wystarczy, aby sprawdzić ich nierówności z

where (A<>B) 

Albo muszę jednoznacznie sprawdzić to w ten sposób:

WHERE ((A <> B) OR (A IS NOT NULL AND B IS NULL) OR (A IS NULL AND B IS NOT NULL)) 

ODWOŁUJ SIĘ do tego thread, aby uzyskać odpowiedź na to pytanie.

+0

W skrócie, ' anything = NULL' ma wartość NULL (ani true, ani false). i 'coś <> NULL' również ma wartość NULL. –

Odpowiedz

25

relacyjne wyrażenia udziałem NULL faktycznie uzyskując null ponownie

edit

tu <> oznacza dowolnego operatora binarnego, NULL jest zastępczy SQL i value jest dowolna wartość (NULL jest nie wartość):

  • NULL <> value ->NULL
  • NULL <> NULL ->NULL

logika jest: NULL oznacza „bez wartości” lub „nieznaną wartość”, a stąd wszelkie porównania z jakąkolwiek rzeczywistą wartościąnie ma sensu.

jest X = 42 prawdziwe, fałszywe, albo nie wiadomo, biorąc pod uwagę, że nie wiem, co wartość (jeśli dowolny) X trzyma? SQL twierdzi, że jest nieznany. jest X = Y prawda, fałsz lub nieznany, ponieważ oba są nieznane? SQL mówi, że wynikiem jest nieznany. i mówi tak dla każdej binarnej operacji relacyjnej, która jest tylko logiczna (nawet jeśli posiadanie NULL w modelu nie jest na pierwszym miejscu).

SQL również dwa jednoargumentowy operatorów PostFix, IS NULL i IS NOT NULL, to powrót prawda czy fałsz w zależności od ich operandów.

  • NULL IS NULL ->TRUE
  • NULL IS NOT NULL ->FALSE
+0

Hej, po przeczytaniu twojego wyjaśnienia dostaję "błąd kompilacji w mojej głowie". Dlaczego nawet porównanie binarne jest dozwolone? Jeśli napiszę "wybierz * z A, gdzie A.xxx <> null", otrzymuję pusty zestaw wyników. Jeśli jednak napiszę "wybierz * z A, gdzie null", jest to błąd składniowy. Więc coś nie działa dla mnie z wyjaśnieniem "value <> null => null". Czy możesz mi pomóc myśleć w ten sposób "w odpowiedni sposób"? – dingalapadum

+0

Czy to możliwe, że bardziej sensowne byłoby myślenie o tym, jak np. "Value <> null => false' i" value = null => false'? Pozwoli to uniknąć błędu typu, o którym mówię. Ponadto, podobnie jak to, można zrozumieć, co oznacza coś podobnego do 'value <> null AND 1 = 1', podczas gdy' null AND 1 = 1' znowu byłoby syntaktycznie dziwne ... jak już powiedziałem, po prostu próbuję owinąć się wokół tego. – dingalapadum

+0

'foo OP NULL' jest dozwolone, ponieważ SQL jest uszkodzony. –

3

Krótka odpowiedź brzmi ... NULL są dziwne, nie zachowują się tak, jak można się spodziewać.

Oto świetny artykuł na temat działania NULL w SQL. Myślę, że pomoże to w lepszym zrozumieniu tematu. Myślę, że sekcje dotyczące obsługi wartości null w wyrażeniach będą szczególnie przydatne dla Ciebie.

http://www.oracle.com/technology/oramag/oracle/05-jul/o45sql.html

7

Wszystkie porównania z udziałem null są niezdefiniowane i oceniać na false. Pomysł ten, który zapobiega ocenienie null jako równoważnej null, również zapobiega ocenienie null jako NIE równoważnej null.

+1

Nie wiem, kto to zignorował. Każde porównanie obejmujące 'null's inne niż' is' zwróci false na DB, która podąża za standardem SQL. – Donnie

+0

@Donnie: Dzięki, zastanawiałem się, gdzie się myliłem. –

+3

Zrobiłem. jakiekolwiek porównanie z wartością null zwróci NULL –

33

Ponieważ to zachowanie następująco założona ternary logic gdzie NULL jest traktowany jako wartość nieznana.

Jeśli uważasz NULL jako nieznane, staje się o wiele bardziej intuicyjny:

Czy unknown a równa unknown b? Nie da się tego dowiedzieć: unknown.

+3

Świetna perspektywa! Innym sposobem patrzenia na to jest to, że jeśli "nieznane a" jest równe "nieznanemu b", to tak naprawdę nie mogą one być tak nieznane, ponieważ wiesz coś o nich. Rodzaj mechaniki kwantowej-y. – womp

+0

@Womp: Rzeczywiście wiesz, że nie wiesz;) –

3

Domyślne zachowanie (ANSI) wartości null w wyrażeniu spowoduje wartość zerową (w przypadku tego przypadku jest wystarczająco dużo innych odpowiedzi).

Istnieje jednak kilka przypadków krawędzi i zastrzeżeń, które umieściłabym podczas pracy z MS Sql Server, których nie ma na liście.

  • Nulls w oświadczeniu, które grupuje wartości razem, będą uważane za równe i będą zgrupowane razem.
  • Wartości puste w wyciągu, który je zamawia, będą uznawane za równe.
  • wartości Null wybrane w oświadczeniu, że używa odrębne będą uznawane za równe przy ocenie odrębny aspekt zapytania

Jest to możliwe w SQL Server, aby zastąpić logikę ekspresji w odniesieniu do określonej Null = Null testy, za pomocą SET ANSI_NULLS OFF, co da ci równość między wartościami zerowymi - nie jest to zalecane, ale istnieje.

SET ANSI_NULLS OFF 

select result = 
    case 
     when null=null then 'eq' 
     else 'ne' 
    end 

SET ANSI_NULLS ON 

select result = 
    case 
     when null=null then 'eq' 
     else 'ne' 
    end 
0

"Czy nieznany jest równy nieznanemu b? Nie ma sposobu, aby wiedzieć, więc: nieznany."

Pytanie brzmiało: dlaczego porównanie daje FALSE?

Przy logice trójwartościowej rozsądnie byłoby, gdyby porównanie dało NIEZNANY (nie FALSE). Ale SQL nie daje FALSE, a nie UNKNOWN.

Jednym z miriadów perwersji w języku SQL.

Ponadto należy brać pod uwagę:

Jeśli „unkown” jest wartością logiczną w potrójnym logiki, to powinno to być przypadek, że porównanie równość dwóch wartości logicznych, które zarówno zdarzają się (wartość dla) "nieznany", to porównanie powinno dać TRUE.

Jeśli sama wartość logiczna jest nieznana, to oczywiście nie można jej przedstawić, umieszczając tam wartość "nieznana", ponieważ oznaczałoby to, że znana jest wartość logiczna ("nieznana"). To znaczy, jak teoria relacyjna udowadnia, że ​​implementacja logiki trójwartościowej podnosi wymóg logiki czterowartościowej, że logika 4-wycenowa prowadzi do potrzeby logiki 5-cio wartościowej, itd. Itd. W nieskończoności.

2

Oto Quick Fix

ISNULL (A, 0) = ISNULL (B, 0)

0 można zmienić na coś, co nigdy nie może się zdarzyć w danych

Powiązane problemy