In SQL Server, cosa significa "SET ANSI_NULLS ON"?


92

La definizione dice:

Quando SET ANSI_NULLS è ON, un'istruzione SELECT che utilizza WHERE nome_colonna = NULL restituisce zero righe anche se sono presenti valori null in nome_colonna. Un'istruzione SELECT che utilizza WHERE nome_colonna <> NULL restituisce zero righe anche se in nome_colonna sono presenti valori non null.

Significa che in questa query non verranno inclusi valori nulli?

SELECT Region
FROM employees
WHERE Region = @region

O ANSI_NULLriguarda solo query come questa (dove WHEREinclude la parola specifica NULL)?

SELECT Region
FROM employees
WHERE Region = NULL

1
La risposta non è già presente nel 4 ° paragrafo della documentazione ufficiale da cui hai copiato il 1 ° paragrafo, che è: -> "SET ANSI_NULLS ON influisce su un confronto solo se uno degli operandi del confronto è una variabile che è NULL o un valore letterale NULL. Se entrambi i lati del confronto sono colonne o espressioni composte, l'impostazione non influisce sul confronto. "
user1451111

Risposte:


68

Significa che nessuna riga verrà restituita se @regionè NULL, se utilizzata nel primo esempio, anche se sono presenti righe nella tabella in cui si Regiontrova NULL.

Quando ANSI_NULLSè attivo (che dovresti sempre impostare comunque, poiché l'opzione per non averlo verrà rimossa in futuro), qualsiasi operazione di confronto in cui (almeno) uno degli operandi è NULLproduce il terzo valore logico - UNKNOWN( al contrario di TRUEe FALSE).

UNKNOWNi valori si propagano attraverso qualsiasi combinazione di operatori booleani se non sono già decisi (ad esempio ANDcon un FALSEoperando o ORcon un TRUEoperando) o negazioni ( NOT).

La WHEREclausola viene utilizzata per filtrare il set di risultati prodotto dalla FROMclausola, in modo tale che il valore complessivo della WHEREclausola deve essere TRUEaffinché la riga non venga filtrata. Quindi, se un confronto UNKNOWNviene prodotto da qualsiasi confronto, la riga verrà filtrata.


La risposta di @ user1227804 include questa citazione:

Se entrambi i lati del confronto sono colonne o espressioni composte, l'impostazione non influisce sul confronto.

da *SET ANSI_NULLS

Tuttavia, non sono sicuro di quale punto stia cercando di fare, poiché se NULLvengono confrontate due colonne (ad esempio in a JOIN), il confronto non riesce ancora:

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

La query precedente restituisce 0 righe, mentre:

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)

Restituisce una riga. Quindi, anche quando entrambi gli operandi sono colonne, NULLnon è uguale NULL. E la documentazione per= non ha nulla da dire sugli operandi:

Quando confronti due NULLespressioni, il risultato dipende ANSI_NULLSdall'impostazione:

Se ANSI_NULLSè impostato su ON, il risultato è NULL1 , seguendo la convenzione ANSI che un valore NULL(o sconosciuto) non è uguale a un altro NULLo sconosciuto.

Se ANSI_NULLSè impostato su OFF, il risultato di NULLrispetto a NULLè TRUE.

Il confronto NULLcon un non NULLvalore risulta sempre in FALSE2 .

Tuttavia, sia 1 che 2 non sono corretti: il risultato di entrambi i confronti lo è UNKNOWN.


* Il significato criptico di questo testo è stato finalmente scoperto anni dopo. Ciò che in realtà significa è che, per questi confronti, l'impostazione non ha effetto e si comporta sempre come se l'impostazione fosse ON . Sarebbe stato più chiaro se avesse affermato che SET ANSI_NULLS OFFera l'impostazione che non ha avuto alcun effetto.


1
quindi se ho capito bene: ha effetto anche sul risultato della frase "Where Region = @region" e non solo quando scrivo specificamente "Where Region = null"?
Rodniko

7

Se @Regionnon è un nullvalore (diciamo @Region = 'South') non restituirà righe in cui il campo Region è nullo, indipendentemente dal valore di ANSI_NULLS.

ANSI_NULLS farà la differenza solo quando il valore di @Regionè null, cioè quando la tua prima query diventa essenzialmente la seconda.

In tal caso, ANSI_NULLS ON non restituirà alcuna riga (perché null = nullprodurrà un valore booleano sconosciuto (aka null)) e ANSI_NULLS OFF restituirà tutte le righe in cui il campo Region è nullo (perché null = nullrestituirà true)


6

Se ANSI_NULLS è impostato su "ON" e se applichiamo =, <> sul valore della colonna NULL durante la scrittura dell'istruzione select, non restituirà alcun risultato.

Esempio

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

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

IMPOSTARE 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)

IMPOSTARE 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)

2
+1 per essere l'UNICA risposta che distingue chiaramente tra WHERE X IS NULLe WHERE X = NULLe come ANSI_NULLS influisce sul risultato. Nonostante i tentativi più zelanti dei votanti verso il basso, QUESTA dovrebbe essere la risposta accettata!
Riegardt Steyn

1
+1 per spiegare utilizzando esempi, che saranno sempre più chiari e concisi piuttosto che frasi lunghe.
peter.aryanto

3

IMPOSTARE ANSI_NULLS ON

IT Restituisce tutti i valori compresi i valori nulli nella tabella

SET ANSI_NULLS off

Termina quando le colonne contengono valori nulli


2
Che cosa aggiunge questa risposta alle risposte già indicate? Diffidare di aggiungere nuove risposte a vecchie domande - Dovrebbero contenere spiegazioni estese su soluzioni già pubblicate o fornire nuove informazioni - Dalla recensione
Takarii

1

Immagino che la cosa principale qui sia:

Mai utente:

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

Usa sempre:

  • @anything IS NULL
  • @anything IS NOT NULL

0

Impostando ANSI NULLS su OFF, la comparazione NULL = NULL restituirà true. PER ESEMPIO :

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

restituirà alcuni risultati come mostrato di seguito: zcwInvoiceDeliveryType 744547 NULL zcExpenseRptStatusTrack 2099048 NULL ZCVendorPermissions 2840564 NULL ZCWOrgLevelClientFee 4322525 NULL

Sebbene questa query non restituirà alcun risultato:

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

0

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

Quando SET ANSI_NULLS è ON, un'istruzione SELECT che utilizza WHERE nome_colonna = NULL restituisce zero righe anche se sono presenti valori null in nome_colonna. Un'istruzione SELECT che utilizza WHERE nome_colonna <> NULL restituisce zero righe anche se sono presenti valori non nulli in nome_colonna.

Per es

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 !
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.