Was bedeutet in SQL Server "SET ANSI_NULLS ON"?

90

Die Definition sagt:

Wenn SET ANSI_NULLS aktiviert ist, gibt eine SELECT-Anweisung, die WHERE Spaltenname = NULL verwendet, Nullzeilen zurück, auch wenn Spaltenname Nullwerte enthält. Eine SELECT-Anweisung, die WHERE Spaltenname <> NULL verwendet, gibt Nullzeilen zurück, auch wenn Spaltenname Nicht-Null-Werte enthält.

Bedeutet dies, dass diese Abfrage keine Nullen enthält?

SELECT Region
FROM employees
WHERE Region = @region

Oder handelt es ANSI_NULLsich nur um Anfragen wie diese (bei denen WHEREdas spezifische Wort enthalten ist NULL)?

SELECT Region
FROM employees
WHERE Region = NULL
Rodniko
quelle
1
Ist die Antwort nicht bereits im 4. Absatz der offiziellen Dokumentation enthalten, aus der Sie den 1. Absatz kopiert haben? -> "SET ANSI_NULLS ON wirkt sich nur dann auf einen Vergleich aus, wenn einer der Operanden des Vergleichs eine Variable ist, die NULL ist oder ein Literal NULL. Wenn beide Seiten des Vergleichs Spalten oder zusammengesetzte Ausdrücke sind, wirkt sich die Einstellung nicht auf den Vergleich aus. "
user1451111

Antworten:

66

Es bedeutet , dass keine Zeilen zurückgegeben werden , wenn @regionist NULL, wenn in Ihrem ersten Beispiel verwendet wird , auch wenn es Zeilen in der Tabelle , wo Regionist NULL.

Wenn aktiviert ANSI_NULLSist (was Sie sowieso immer aktivieren sollten, da die Option, es nicht zu aktivieren, in Zukunft entfernt wird), erzeugt jede Vergleichsoperation, bei der (mindestens) einer der Operanden ausgeführt wird, NULLden dritten logischen Wert - UNKNOWN( im Gegensatz zu TRUEund FALSE).

UNKNOWNWerte verbreiten sich durch alle kombinierenden booleschen Operatoren, wenn sie nicht bereits entschieden wurden (z. B. ANDmit einem FALSEOperanden oder ORmit einem TRUEOperanden) oder negations ( NOT).

Die WHEREKlausel wird verwendet, um die von der FROMKlausel erzeugte Ergebnismenge zu filtern , sodass der Gesamtwert der WHEREKlausel sein muss, TRUEdamit die Zeile nicht herausgefiltert wird. Wenn UNKNOWNalso durch einen Vergleich ein erzeugt wird, wird die Zeile herausgefiltert.


Die Antwort von @ user1227804 enthält dieses Zitat:

Wenn beide Seiten des Vergleichs Spalten oder zusammengesetzte Ausdrücke sind, wirkt sich die Einstellung nicht auf den Vergleich aus.

von *SET ANSI_NULLS

Ich bin mir jedoch nicht sicher, welchen Punkt es anstrebt, da beim NULLVergleich zweier Spalten (z. B. in a JOIN) der Vergleich immer noch fehlschlägt:

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

Die obige Abfrage gibt 0 Zeilen zurück, während:

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)

Gibt eine Zeile zurück. Selbst wenn beide Operanden Spalten sind, ist NULLdies nicht gleich NULL. Und die Dokumentation zu= hat nichts zu den Operanden zu sagen:

Wenn Sie zwei NULLAusdrücke vergleichen , hängt das Ergebnis von der ANSI_NULLSEinstellung ab:

Wenn auf ANSI_NULLSgesetzt ist, ONist das Ergebnis NULL1 , gemäß der ANSI-Konvention, dass ein NULL(oder unbekannter) Wert nicht gleich einem anderen NULLoder unbekannten Wert ist.

Wenn ANSI_NULLSfestgelegt ist OFF, das Ergebnis im NULLVergleich zu NULList TRUE.

Der Vergleich NULLmit einem Nichtwert NULLergibt immer FALSE2 .

Sowohl 1 als auch 2 sind jedoch falsch - das Ergebnis beider Vergleiche ist UNKNOWN.


* Die kryptische Bedeutung dieses Textes wurde Jahre später entdeckt. Was es tatsächlich bedeutet, ist, dass für diese Vergleiche die Einstellung keine Auswirkung hat und sich immer so verhält, als ob die Einstellung eingeschaltet wäre . Wäre klarer gewesen, wenn angegeben worden wäre, dass dies SET ANSI_NULLS OFFdie Einstellung war, die keinen Einfluss hatte.

Damien_The_Unbeliever
quelle
1
Also, wenn ich Sie richtig verstehe: Es wirkt sich auch auf das Ergebnis der Phrase "Where Region = @region" aus und nicht nur, wenn ich speziell "Where Region = null" schreibe?
Rodniko
6

Wenn @Regiones sich nicht um einen nullWert handelt (z. B. @Region = 'South'), werden unabhängig vom Wert von ANSI_NULLS keine Zeilen zurückgegeben, in denen das Feld Region null ist.

ANSI_NULLS macht nur dann einen Unterschied, wenn der Wert von @Regionist null, dh wenn Ihre erste Abfrage im Wesentlichen die zweite wird.

In diesem Fall gibt ANSI_NULLS ON keine Zeilen zurück (da dies null = nulleinen unbekannten booleschen Wert ergibt (auch bekannt als null)), und ANSI_NULLS OFF gibt alle Zeilen zurück, in denen das Feld Region null ist (weil dies null = nullergibt true).

SWeko
quelle
4

Wenn ANSI_NULLS auf "ON" gesetzt ist und wir beim Schreiben der select-Anweisung =, <> auf den NULL-Spaltenwert anwenden, wird kein Ergebnis zurückgegeben.

Beispiel

create table #tempTable (sn int, ename varchar(50))

insert into #tempTable
values (1, 'Manoj'), (2, 'Pankaj'), (3, NULL), (4, 'Lokesh'), (5, 'Gopal')

SET ANSI_NULLS ON

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)

SET ANSI_NULLS OFF

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)
Pravat Behuria
quelle
2
+1 für die EINZIGE Antwort, die klar zwischen WHERE X IS NULLund WHERE X = NULLunterscheidet und wie ANSI_NULLS das Ergebnis beeinflusst. Trotz der übereifrigen Versuche der Wähler nach unten sollte DIES die akzeptierte Antwort sein!
Riegardt Steyn
1
+1 für die Erklärung anhand von Beispielen, die immer klarer und prägnanter sind als lange Sätze.
Peter.aryanto
3

SET ANSI_NULLS ON

IT Gibt alle Werte einschließlich der Nullwerte in der Tabelle zurück

SET ANSI_NULLS aus

Es endet, wenn Spalten Nullwerte enthalten

Josef Stalin
quelle
2
Welches Extra fügt diese Antwort zu den bereits angegebenen Antworten hinzu? Seien Sie vorsichtig beim Hinzufügen neuer Antworten auf alte Fragen - Sie sollten erweiterte Erklärungen zu bereits veröffentlichten Lösungen enthalten oder neue Erkenntnisse liefern - Aus der Überprüfung
Takarii
1

Ich denke, die Hauptsache hier ist:

Niemals Benutzer:

  • @anything = NULL
  • @anything <> NULL
  • @anything != null

Verwenden Sie immer:

  • @anything IS NULL
  • @anything IS NOT NULL
user369142
quelle
0

Wenn Sie ANSI NULLS OFF setzen, wird die Vergleichsrückgabe NULL = NULL true. Z.B :

        SET ANSI_NULLS OFF
        select * from sys.tables
        where principal_id = Null

gibt ein Ergebnis zurück, wie unten angezeigt: zcwInvoiceDeliveryType 744547 NULL zcExpenseRptStatusTrack 2099048 NULL ZCVendorPermissions 2840564 NULL ZCWOrgLevelClientFee 4322525 NULL

Während diese Abfrage keine Ergebnisse zurückgibt:

        SET ANSI_NULLS ON 
        select * from sys.tables
        where principal_id = Null
Problemlöser
quelle
0

https://docs.microsoft.com/en-us/sql/t-sql/statements/set-ansi-nulls-transact-sql

Wenn SET ANSI_NULLS aktiviert ist, gibt eine SELECT-Anweisung, die WHERE Spaltenname = NULL verwendet, Nullzeilen zurück, auch wenn Spaltenname Nullwerte enthält. Eine SELECT-Anweisung, die WHERE spaltenname <> NULL verwendet, gibt null Zeilen zurück, auch wenn in spaltenname nicht null Werte enthalten sind.

Zum Beispiel

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 !
Prasanth VJ
quelle