Definicja mówi:
Gdy SET ANSI_NULLS jest ON, instrukcja SELECT, która używa WHERE nazwa_kolumny = NULL, zwraca zero wierszy, nawet jeśli w kolumnie nazwa_kolumny znajdują się wartości null. Instrukcja SELECT, która używa WHERE nazwa_kolumny <> NULL, zwraca zero wierszy, nawet jeśli w kolumnie nazwa_kolumny znajdują się wartości inne niż null.
Czy to oznacza, że w tym zapytaniu nie zostaną uwzględnione żadne wartości null?
SELECT Region
FROM employees
WHERE Region = @region
A może ANSI_NULL
dotyczy tylko zapytań takich jak to (gdzie w WHERE
zawiera określone słowo NULL
)?
SELECT Region
FROM employees
WHERE Region = NULL
sql
tsql
stored-procedures
Rodniko
źródło
źródło
Odpowiedzi:
Oznacza to, że nie wiersze zostaną zwrócone, jeśli
@region
jestNULL
, kiedy jest stosowany w pierwszym przykładzie, nawet jeśli istnieją wiersze w tabeli, gdzieRegion
jestNULL
.Kiedy
ANSI_NULLS
jest włączone (które i tak należy zawsze ustawiać, ponieważ opcja nie włączania tej funkcji zostanie w przyszłości usunięta), każda operacja porównania, w której (przynajmniej) jeden z operandówNULL
daje trzecią wartość logiczną -UNKNOWN
( w przeciwieństwie doTRUE
iFALSE
).UNKNOWN
wartości są propagowane przez dowolne łączące operatory boolowskie, jeśli nie zostały jeszcze określone (np.AND
zFALSE
operandem lubOR
zTRUE
operandem) lub przez negacje (NOT
).WHERE
Klauzuli filtrujące zbioru wyników wytwarzanego przezFROM
klauzulą, tak, że ogólna wartośćWHERE
musi ono byćTRUE
w rzędzie nie są filtrowane. Tak więc, jeśliUNKNOWN
zostanie utworzone przez jakiekolwiek porównanie, spowoduje to odfiltrowanie wiersza.@ user1227804 za odpowiedź zawiera ten cytat:
od *
SET ANSI_NULLS
Nie jestem jednak pewien, o co chodzi, ponieważ jeśli
NULL
porównuje się dwie kolumny (np. W aJOIN
), porównanie nadal się nie udaje:create table #T1 ( ID int not null, Val1 varchar(10) null ) insert into #T1(ID,Val1) select 1,null create table #T2 ( ID int not null, Val1 varchar(10) null ) insert into #T2(ID,Val1) select 1,null select * from #T1 t1 inner join #T2 t2 on t1.ID = t2.ID and t1.Val1 = t2.Val1
Powyższe zapytanie zwraca 0 wierszy, podczas gdy:
select * from #T1 t1 inner join #T2 t2 on t1.ID = t2.ID and (t1.Val1 = t2.Val1 or t1.Val1 is null and t2.Val1 is null)
Zwraca jeden wiersz. Więc nawet jeśli oba operandy są kolumnami,
NULL
nie jest równeNULL
. A dokumentacja dla=
nie ma nic do powiedzenia na temat operandów:Jednak zarówno 1 , jak i 2 są nieprawidłowe - wynik obu porównań jest taki
UNKNOWN
.* Tajemnicze znaczenie tego tekstu zostało ostatecznie odkryte wiele lat później. W rzeczywistości oznacza to, że dla tych porównań ustawienie nie ma wpływu i zawsze działa tak, jakby było włączone . Byłoby jaśniejsze, gdyby stwierdził, że
SET ANSI_NULLS OFF
to ustawienie nie ma żadnego wpływu.źródło
Jeśli
@Region
nie jestnull
wartością (powiedzmy@Region = 'South'
), nie zwróci wierszy, w których pole Region ma wartość null, niezależnie od wartości ANSI_NULLS.ANSI_NULLS będzie miało znaczenie tylko wtedy, gdy wartość
@Region
isnull
, tj. Gdy pierwsze zapytanie stanie się w zasadzie drugim.W takim przypadku ANSI_NULLS ON nie zwróci żadnych wierszy (ponieważ
null = null
zwróci nieznaną wartość logiczną (akanull
)), a ANSI_NULLS OFF zwróci wszystkie wiersze, w których pole Region ma wartość null (ponieważnull = null
datrue
)źródło
Jeśli ANSI_NULLS jest ustawione na „ON” i jeśli zastosujemy =, <> na wartość kolumny NULL podczas pisania instrukcji select, to nie zwróci żadnego wyniku.
Przykład
create table #tempTable (sn int, ename varchar(50)) insert into #tempTable values (1, 'Manoj'), (2, 'Pankaj'), (3, NULL), (4, 'Lokesh'), (5, 'Gopal')
WŁĄCZ ANSI_NULLS
select * from #tempTable where ename is NULL -- (1 row(s) affected) select * from #tempTable where ename = NULL -- (0 row(s) affected) select * from #tempTable where ename is not NULL -- (4 row(s) affected) select * from #tempTable where ename <> NULL -- (0 row(s) affected)
WYŁĄCZ ANSI_NULLS
select * from #tempTable where ename is NULL -- (1 row(s) affected) select * from #tempTable where ename = NULL -- (1 row(s) affected) select * from #tempTable where ename is not NULL -- (4 row(s) affected) select * from #tempTable where ename <> NULL -- (4 row(s) affected)
źródło
WHERE X IS NULL
iWHERE X = NULL
oraz jak ANSI_NULLS wpływa na wynik. Pomimo wysiłków nadmiernie zagorzałych wyborców, TO powinna być akceptowana odpowiedź!WŁĄCZ ANSI_NULLS
IT Zwraca wszystkie wartości, w tym wartości null w tabeli
WYŁĄCZ ANSI_NULLS
kończy się, gdy kolumny zawierają wartości null
źródło
Myślę, że najważniejsze jest to:
Nigdy nie używaj :
@anything = NULL
@anything <> NULL
@anything != null
Zawsze używaj:
@anything IS NULL
@anything IS NOT NULL
źródło
Ustawienie ANSI NULLS OFF spowoduje, że porównanie NULL = NULL zwróci wartość true. EG:
SET ANSI_NULLS OFF select * from sys.tables where principal_id = Null
zwróci niektóre wyniki, jak pokazano poniżej: zcwInvoiceDeliveryType 744547 NULL zcExpenseRptStatusTrack 2099048 NULL ZCVendorPermissions 2840564 NULL ZCWOrgLevelClientFee 4322525 NULL
Chociaż to zapytanie nie zwróci żadnych wyników:
SET ANSI_NULLS ON select * from sys.tables where principal_id = Null
źródło
https://docs.microsoft.com/en-us/sql/t-sql/statements/set-ansi-nulls-transact-sql
Gdy SET ANSI_NULLS jest ON, instrukcja SELECT, która używa WHERE nazwa_kolumny = NULL, zwraca zero wierszy, nawet jeśli w kolumnie nazwa_kolumny znajdują się wartości null. Instrukcja SELECT, która używa WHERE nazwa_kolumny <> NULL, zwraca zero wierszy, nawet jeśli w kolumnie nazwa_kolumny znajdują się wartości inne niż null.
Np
DECLARE @TempVariable VARCHAR(10) SET @TempVariable = NULL SET ANSI_NULLS ON SELECT 'NO ROWS IF SET ANSI_NULLS ON' where @TempVariable = NULL -- IF ANSI_NULLS ON , RETURNS ZERO ROWS SET ANSI_NULLS OFF SELECT 'THERE WILL BE A ROW IF ANSI_NULLS OFF' where @TempVariable =NULL -- IF ANSI_NULLS OFF , THERE WILL BE ROW !
źródło