2010-12-15 10 views
17

Mam tabelę, która ma kolumnę wartości, które mogą być rowTypeID = (1,2,3 lub null). Chciałbym napisać zapytanie, które zwraca dowolny wiersz, który nie ma wartości 3 w nim. W tym przykładzie chcę wszystkie NULL wiersze wraz ze wszystkimi 1,2 wiersze po prostu nie chcę wierszy o wartości 3Powrót SQL Server Wiersze, które nie są równe <> do wartości i NULL

Ustaw ANSI null ON jest obecnie ustawiony dla bazy danych.

Jestem ciekaw, dlaczego nie mogę napisać

select * from myTable where myCol <> 3 

To zapytanie nie zwróci żadnych wierszy, które mają wartość NULL w kolumnie Mycol

muszę napisać

select * from my Table where myCol <> 3 or myCol Is NULL 

Czy zawsze muszę dołączyć IS NULL lub czy mogę to ustawić, aby klauzula where myCol <> 3 zwróci wiersze, które mają wartość Null jako wartość dla mojego Col

+13

To jest sposób NULL działa, każde porównanie z nim jest fałszywe, z wyjątkiem IS NULL i NIE JEST NULL – kurosch

+0

@kurosch: Ostrożnie po linii, NULL = NULL również zwróci false, ponieważ jest to porównanie? – Marcel

+2

@Marcel: tak, NULL = NULL jest zawsze fałszem, a dla tej sprawy tak jest NULL <> NULL :-) – kurosch

Odpowiedz

14

Myślę, że podejście jest w porządku:

SELECT * 
FROM MyTable 
WHERE myCol <> 3 OR myCol IS NULL 

Skoro pytasz alternatyw, inny sposób to zrobić jest, aby Państwa kolumnę NOT NULL i zapisać kolejny (otherwised nieużywany) wartości w bazie danych zamiast NULL - na przykład -1. Następnie wyrażenie myCol <> 3 będzie pasować do twojego fałszywego-NULL, tak jak przy każdej innej wartości.

SELECT * 
FROM MyTable 
WHERE myCol <> 3 

Jednak ogólnie polecam nie używać tego podejścia. Sposób, w jaki już to robisz, jest właściwą drogą.

także być może warto wspomnieć, że kilka innych baz danych obsługują IS DISTINCT FROM który robi dokładnie to, co chcesz:

SELECT * 
FROM MyTable 
WHERE myCol IS DISTINCT FROM 3 

MySQL ma NULL-safe equal który może być również używany do tego celu:

SELECT * 
FROM MyTable 
WHERE NOT myCol <=> 3 

Niestety SQL Server nie obsługuje jeszcze żadnej z tych składni.

+0

Powtórz tę funkcję ISO na stronie MS, "DISTINCT PREDICATE": https://connect.microsoft.com/SQLServer/feedback/details/286422/add-language-and-optimizer-support-for-iso-distinct-predicate – montewhizdoh

2

Po każdym przetestowaniu wartości wszystkie wartości NULL są pomijane - w końcu testujesz, czy wartość w niektórych kolumnach spełnia określone kryteria, a wartość NULL to , a nie wartość.

3

Musisz obsłużyć NULL w taki czy inny sposób, ponieważ wyrażenia dotyczą NULLevaluate to Unknown. Jeśli chcesz, możesz zamiast tego zrobić:

select * 
from MyTable 
where isnull(MyColumn, -1) <> 3 

Jednak wiąże się to magiczna liczba (-1), i jest zapewne mniej czytelny niż oryginalny test IS NULL.

Edytuj: i, jak wskazuje SQLMenace, nie jest SARGable.

+3

nie sargable ... – SQLMenace

+0

select * z MyTable gdzie IsNull (MyColumn, 3) = 3 – nothrow

+0

@ SQLMenace: dobra racja, również będzie gorsza - nie polecam mojej sugestii. – RedFilter

0

ponieważ nie można porównać do niczego innego NULL, NULL nie jest nawet równa NULL

DECLARE @i INT 
DECLARE @i2 INT 

SELECT @i = NULL, @i2 = NULL 

IF @i = @i2 
PRINT 'equal' 
ELSE 
PRINT 'not equal' 
1

Czy zawsze muszą zawierać IS NULL czy mogę go ustawić tak WHERE myCol <> 3 zwróci wiersze, które mają wartość Null jako wartość dla mojego Col?

Ty zawsze, zawsze, zawsze muszą zawierać is null.

Ponieważ 3 nie jest równe Nie dotyczy i nie jest równe Unkown.

Powiązane problemy