Czy ktoś mógłby wyjaśnić następujące zachowanie w 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)
Czy ktoś mógłby wyjaśnić następujące zachowanie w 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)
Odpowiedzi:
<>
to Standard SQL-92; !=
jest jego odpowiednikiem. Oba oceniają wartości, które NULL
nie są - NULL
jest symbolem zastępczym, który mówi, że nie ma wartości.
Dlatego możesz używać IS NULL
/ IS NOT NULL
jako predykatów tylko w takich sytuacjach.
To zachowanie nie jest specyficzne dla SQL Server. Wszystkie dialekty SQL zgodne ze standardami działają w ten sam sposób.
Uwaga : Aby porównać, jeśli twoja wartość nie jest równa null , użyj IS NOT NULL
, natomiast do porównania z wartością inną niż null , użyj <> 'YOUR_VALUE'
. Nie mogę powiedzieć, czy moja wartość jest równa NULL, ale mogę powiedzieć, czy moja wartość to NULL, czy NIE NULL. Mogę porównać, jeśli moja wartość jest inna niż NULL.
!=
aż ~ 9i, jak rozumiem, co przyniosło wiele składni ANSI-92. Wierzę, że MySQL jest podobny, zaczynając wsparcie w 4.x.
!=
mógł zostać włączony do późniejszej specyfikacji jako alternatywa dla <>
. Nie mam nowych specyfikacji, więc nie mogę być tego pewien.
WHERE MyColumn != NULL
lub WHERE MyColumn = NULL
deterministyczny? Innymi słowy, czy gwarantuje, że zawsze zwróci 0 wierszy, bez względu na MyColumn
to, czy w bazie danych jest dopuszczalna wartość null?
!=
tylko ocenia wartości, zrobienie czegoś podobnego WHERE MyColumn != 'somevalue'
nie zwróci rekordów NULL.
Wartość NULL nie ma wartości, dlatego nie można jej porównywać za pomocą operatorów wartości skalarnych.
Innymi słowy, żadna wartość nigdy nie może być równa (lub nie być równa) NULL, ponieważ NULL nie ma żadnej wartości.
Dlatego SQL ma specjalne predykaty IS NULL i IS NOT NULL do obsługi NULL.
'a' != null
NIE zwracanie wartości ( true
/ 1
) jest sprzeczne z intuicją i od czasu do czasu mnie łapie! Myślałem, że „pewna wartość w porównaniu do żadnej wartości” zawsze będzie „nie równa”, ale może to tylko ja?!?
SELECT * FROM MyTable WHERE coalesce(MyColumn, 'x') <> 'x'
można przypisać stałą, jeśli jest to NULL, pod warunkiem, że podasz odpowiedni typ danych dla wartości wartownika x (w tym przypadku ciąg / char). Jest to składnia TSQL, ale Oracle i inne silniki mają podobne funkcje.
Należy pamiętać, że takie zachowanie jest zachowaniem domyślnym (ANSI).
Jeśli ty:
SET ANSI_NULLS OFF
http://msdn.microsoft.com/en-us/library/ms188048.aspx
Otrzymasz różne wyniki.
SET ANSI_NULLS OFF
najwyraźniej odejdzie w przyszłości ...
create unique index UK_MyTable on MyTable (Column) where Column is not null
): Msdn.microsoft.com/en-us/library/cc280372.aspx
SET ANSI_NULLS
jest wyłączona, operatory porównania równe (=) i nierówne (<>) nie są zgodne ze standardem ISO. Instrukcja SELECT, która używa, WHERE column_name = NULL
zwraca wiersze o wartości null w kolumnie nazwa_kolumny. WHERE column_name <> NULL
Użyta instrukcja SELECT zwraca wiersze, które mają niepuste wartości w kolumnie. Ponadto instrukcja SELECT, która używa, WHERE column_name <> XYZ_value
zwraca wszystkie wiersze, które nie są wartościami XYZ i które nie mają wartości NULL. IMHO, to ostatnie stwierdzenie wydaje się trochę dziwne, ponieważ wyklucza wartości zerowe z wyników!
W SQL wszystko oceniasz / obliczasz z NULL
wynikami w NIEZNANY
Dlatego SELECT * FROM MyTable WHERE MyColumn != NULL
lub SELECT * FROM MyTable WHERE MyColumn <> NULL
daje 0 wyników.
Aby zapewnić sprawdzanie NULL
wartości, zapewniona jest funkcja isNull.
Ponadto możesz użyć IS
operatora, tak jak w trzecim zapytaniu.
Mam nadzieję że to pomoże.
Jedyny test na wartość NULL to IS NULL lub IS NOT NULL. Testowanie równości jest nonsensowne, ponieważ z definicji nie wiadomo, jaka jest wartość.
Oto artykuł w Wikipedii do przeczytania:
Używamy
SELECT * FROM MyTable WHERE ISNULL(MyColumn, ' ') = ' ';
aby zwrócić wszystkie wiersze, w których MyColumn ma wartość NULL lub wszystkie wiersze, w których MyColumn jest pustym ciągiem. Dla wielu „użytkowników końcowych” kwestia NULL vs. pusty ciąg znaków jest rozróżnieniem bez potrzeby i zamieszania.
Po prostu nie widzę funkcjonalnego i bezproblemowego powodu, dla którego wartości zerowe nie są porównywalne z innymi wartościami lub innymi wartościami zerowymi, ponieważ możemy je wyraźnie porównać i powiedzieć, że są takie same lub nie w naszym kontekście. To jest zabawne. Właśnie z powodu pewnych logicznych wniosków i konsekwencji musimy stale się tym przejmować. Nie działa, uczyń go bardziej funkcjonalnym i pozostaw filozofom i naukowcom do stwierdzenia, czy jest spójny czy nie, i czy zawiera „uniwersalną logikę”. :) Ktoś może powiedzieć, że to z powodu indeksów lub czegoś innego, wątpię, aby te rzeczy nie mogły być obsługiwane przez wartości zerowe takie same jak wartości. To tak samo, jak porównywanie dwóch pustych kieliszków, jedna to kieliszek do wina, a druga to kufel do piwa, nie porównujemy typów obiektów, ale wartości, które zawierają, tak samo jak można porównać int i varchar, z null it ” jeszcze łatwiej, to nic i to, co łączy ze sobą dwie nicość, są takie same, wyraźnie porównywalne przeze mnie i przez wszystkich innych, którzy piszą sql, ponieważ ciągle łamiemy tę logikę, porównując je w dziwny sposób ze względu na niektóre standardy ANSI. Dlaczego nie skorzystać z mocy komputera, aby zrobić to za nas i wątpię, że spowolniłoby to wszystko, gdyby wszystko związane z tym zostało skonstruowane z myślą o tym. „To nie jest zero, to nic”, to nie jest jabłko, to jest apfel, daj spokój ... Funkcjonalnie jest twoim przyjacielem i jest tu również logika. Ostatecznie jedyną rzeczą, która ma znaczenie, jest funkcjonalność i używanie zer w ten sposób zapewnia mniej więcej funkcjonalność i łatwość użycia. Czy to jest bardziej przydatne? ponieważ ciągle łamiemy tę logikę, porównując je w dziwny sposób z powodu niektórych standardów ANSI. Dlaczego nie skorzystać z mocy komputera, aby zrobić to za nas i wątpię, że spowolniłoby to wszystko, gdyby wszystko związane z tym zostało skonstruowane z myślą o tym. „To nie jest zero, to nic”, to nie jest jabłko, to jest apfel, daj spokój ... Funkcjonalnie jest twoim przyjacielem i jest tu również logika. Ostatecznie jedyną rzeczą, która ma znaczenie, jest funkcjonalność i używanie zer w ten sposób zapewnia mniej więcej funkcjonalność i łatwość użycia. Czy to jest bardziej przydatne? ponieważ ciągle łamiemy tę logikę, porównując je w dziwny sposób z powodu niektórych standardów ANSI. Dlaczego nie skorzystać z mocy komputera, aby zrobić to za nas i wątpię, że spowolniłoby to wszystko, gdyby wszystko związane z tym zostało skonstruowane z myślą o tym. „To nie jest zero, to nic”, to nie jest jabłko, to jest apfel, daj spokój ... Funkcjonalnie jest twoim przyjacielem i jest tu również logika. Ostatecznie jedyną rzeczą, która ma znaczenie, jest funkcjonalność i używanie zer w ten sposób zapewnia mniej więcej funkcjonalność i łatwość użycia. Czy to jest bardziej przydatne? to nie jabłko, to apfel, daj spokój ... Funkcjonalnie jest twoim przyjacielem i tutaj też jest logika. Ostatecznie jedyną rzeczą, która ma znaczenie, jest funkcjonalność i używanie zer w ten sposób zapewnia mniej więcej funkcjonalność i łatwość użycia. Czy to jest bardziej przydatne? to nie jabłko, to apfel, daj spokój ... Funkcjonalnie jest twoim przyjacielem i tutaj też jest logika. Ostatecznie jedyną rzeczą, która ma znaczenie, jest funkcjonalność i używanie zer w ten sposób zapewnia mniej więcej funkcjonalność i łatwość użycia. Czy to jest bardziej przydatne?
Rozważ ten kod:
SELECT CASE WHEN NOT (1 = null or (1 is null and null is null)) THEN 1 ELSE 0 end
Ilu z was wie, co zwróci ten kod? Z lub bez NOT zwraca 0. Dla mnie to nie działa i jest mylące. W c # wszystko jest tak, jak powinno być, operacje porównywania zwracają wartość, logicznie to też tworzy wartość, ponieważ jeśli nie, nie ma nic do porównania (oprócz. Nic :)). Po prostu „powiedzieli”: cokolwiek w porównaniu do null „zwraca” 0, co stwarza wiele obejść i bólów głowy.
Oto kod, który mnie tu przyprowadził:
where a != b OR (a is null and b IS not null) OR (a IS not null and b IS null)
Muszę tylko porównać, jeśli dwa pola (gdzie) mają różne wartości, mógłbym użyć funkcji, ale ...
NULL Nie można porównać do żadnej wartości za pomocą operatorów porównania. NULL = NULL jest fałszem. Null nie jest wartością. Operator IS jest specjalnie zaprojektowany do obsługi porównań NULL.
null = null
co można wykorzystać 1=0
w zapytaniu ad hoc. A jeśli narzekają, zmieniam na null != null
:)
Stare pytanie, ale poniższe mogą zawierać więcej szczegółów.
null
oznacza brak wartości lub nieznaną wartość. Nie określa, dlaczego nie ma wartości, co może prowadzić do niejasności.
Załóżmy, że uruchamiasz takie zapytanie:
SELECT *
FROM orders
WHERE delivered=ordered;
oznacza to, że szukasz wierszy, w których daty ordered
i delivered
są takie same.
Czego można się spodziewać, gdy jedna lub obie kolumny są puste?
Ponieważ co najmniej jedna z dat jest nieznana, nie można oczekiwać, że obie daty będą takie same. Jest tak również w przypadku, gdy oba daty są nieznane: jak mogą być takie same, jeśli nawet nie wiemy, jakie są?
Z tego powodu każde wyrażenie traktowane null
jako wartość musi zawieść. W takim przypadku nie będzie pasować. Dzieje się tak również wtedy, gdy spróbujesz:
SELECT *
FROM orders
WHERE delivered<>ordered;
Ponownie, jak możemy powiedzieć, że dwie wartości nie są takie same, jeśli nie wiemy, czym one są.
SQL ma specyficzny test na brakujące wartości:
IS NULL
W szczególności nie porównuje wartości, ale szuka brakujących wartości.
Wreszcie, jeśli chodzi o !=
operatora, o ile mi wiadomo, nie jest on faktycznie objęty żadnym ze standardów, ale jest bardzo szeroko wspierany. Zostało dodane, aby programiści z niektórych języków czuli się bardziej jak w domu. Szczerze mówiąc, jeśli programista ma trudności z zapamiętaniem używanego języka, zaczyna się źle.
NULL
mamy na myśli, że porównujemy wartość z „posiadaniem NULL
wartości”, a nie z wartością „nieokreślonej wartości, jaką NULL
ma podkład ”? ale której nie wiemy ”, o którym oczywiście nigdy nie będziemy wiedzieć. To naprawdę by to ułatwiło.
IS NULL
jest o wiele bardziej uciążliwe niż pisanie = NULL
. Myślę, że byłoby bardziej spójne, gdyby WHERE columnA = columnB
miało taką samą interpretację WHERE columnA = NULL
, niż traktować tę ostatnią jako szczególny przypadek. Pamiętaj, że NULL
to nie jest wartość. W języków programowania, gdzie to jest uzasadnione, aby przetestować variable == null
to dlatego, że null
ma inne znaczenie; nie reprezentuje czegoś nieznanego, ale celowe resetowanie wartości. Nie w przypadku SQL.
IS NULL
AND =NULL
. Ale spójrz na ostatni Hover. Mam dość ciągłego doświadczania tego, że muszę robić mnóstwo niepotrzebnych? dodatkowe sprawdzanie ...
Chciałbym zasugerować ten kod, który stworzyłem, aby sprawdzić, czy nastąpiła zmiana wartości,
i
będąc nową wartością i d
będąc starą (chociaż kolejność nie ma znaczenia). Z tego powodu zmiana z wartości na null lub odwrotnie jest zmianą, ale z null na null nie jest (oczywiście, od wartości do innej wartości jest zmianą, ale od wartości do tej samej nie jest).
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
Aby skorzystać z tej funkcji, możesz
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
Wyniki są następujące:
---- 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
Zastosowanie sql_variant sprawia, że jest on kompatybilny z różnymi typami
NULL to nic ... nie jest znane. NULL nic nie równa. Dlatego w zapytaniach SQL musisz używać magicznej frazy IS NULL zamiast = NULL
Możesz to odnieść: http://weblogs.sqlteam.com/markc/archive/2009/06/08/60929.aspx
<>
tak jest w specyfikacji 92, ale większość dostawców obsługuje!=
i / lub jest uwzględniona w późniejszej specyfikacji, np. 99 lub 03.