La définition dit:
Lorsque SET ANSI_NULLS est activé, une instruction SELECT qui utilise WHERE nom_colonne = NULL ne renvoie aucune ligne, même s'il existe des valeurs null dans nom_colonne. Une instruction SELECT qui utilise WHERE nom_colonne <> NULL ne renvoie aucune ligne, même s'il existe des valeurs non nulles dans nom_colonne.
Cela signifie-t-il qu'aucune valeur NULL ne sera incluse dans cette requête?
SELECT Region
FROM employees
WHERE Region = @region
Ou faire ANSI_NULL
_ ne concerne que les requêtes comme celle-ci (où WHERE
inclut le mot spécifique NULL
)?
SELECT Region
FROM employees
WHERE Region = NULL
Cela signifie qu'aucune ligne ne sera retournée si @region
est NULL
, lorsqu'il est utilisé dans votre premier exemple, même s'il existe des lignes dans la table où Region
est NULL
.
Quand ANSI_NULLS
est activé (vous devez toujours le définir car l’option de ne pas l’avoir activée sera supprimée dans le futur), toute opération de comparaison où (au moins) l’un des opérandes est NULL
produit la troisième valeur logique - UNKNOWN
(par opposition à TRUE
et FALSE
).
Les valeurs UNKNOWN
se propagent à travers les opérateurs booléens qui combinent si elles ne sont pas déjà décidées (par exemple AND
avec un opérande FALSE
ou OR
avec un TRUE
opérande) ou des négations (NOT
).
La clause WHERE
sert à filtrer le jeu de résultats généré par la clause FROM
, de sorte que la valeur globale de la clause WHERE
doit être TRUE
pour la ligne à ne pas filtrer. Ainsi, si une comparaison UNKNOWN
est produite, la ligne sera filtrée.
@ (User1227804) réponse inclut cette citation:
Si les deux côtés de la comparaison sont des colonnes ou des expressions composées, le paramètre n'affecte pas la comparaison.
de SET ANSI_NULLS
*
Cependant, je ne suis pas sûr du but recherché, car si deux colonnes NULL
sont comparées (par exemple dans un JOIN
), la comparaison échoue toujours:
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 requête ci-dessus renvoie 0 ligne, alors que:
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)
Retourne une ligne. Ainsi, même lorsque les deux opérandes sont des colonnes, NULL
n’est pas égal à NULL
. Et le documentation pour =
n'a rien à dire sur les opérandes:
Lorsque vous comparez deux expressions
NULL
, le résultat dépend duANSI_NULLS
réglage:Si
ANSI_NULLS
est réglé surON
, le résultat estNULL
1, conformément à la convention ANSI, selon laquelle une valeurNULL
(ou inconnue) n’est pas égale à une autreNULL
ou à une valeur inconnue.Si
ANSI_NULLS
est réglé surOFF
, le résultat deNULL
par rapport àNULL
estTRUE
.La comparaison de
NULL
à une valeur autre queNULL
donne toujours lieu àFALSE
2.
Cependant, les deux 1 et 2 sont incorrects - le résultat des deux comparaisons est UNKNOWN
.
*La signification cryptique de ce texte a finalement été découverte des années plus tard. Cela signifie en réalité que, pour ces comparaisons, le paramètre n'a pas d'effet et agit toujours comme si le paramètre était activé . Aurait été plus clair s'il avait déclaré que SET ANSI_NULLS OFF
était le paramètre qui n'a eu aucun effet.
Si @Region
n'est pas une valeur null
(disons @Region = 'South'
) il ne renverra pas les lignes où le champ Region est null, quelle que soit la valeur de ANSI_NULLS.
ANSI_NULLS ne fera la différence que lorsque la valeur de @Region
est null
, c’est-à-dire lorsque votre première requête devient essentiellement la seconde.
Dans ce cas, ANSI_NULLS ON ne renverra aucune ligne (car null = null
donnera une valeur booléenne inconnue (a.k.a. null
)) et ANSI_NULLS OFF retournera toutes les lignes où le champ Region est nul (parce que null = null
donnera true
)
SET ANSI_NULLS ON
IT Retourne toutes les valeurs incluant les valeurs NULL dans la table.
SET ANSI_NULLS off
il se termine lorsque les colonnes contiennent des valeurs nulles
https://docs.Microsoft.com/en-us/sql/t-sql/statements/set-ansi-nulls-transact-sql
Lorsque SET ANSI_NULLS est activé, une instruction SELECT qui utilise WHERE nom_colonne = NULL ne renvoie aucune ligne, même s'il existe des valeurs null dans nom_colonne. Une instruction SELECT qui utilise WHERE nom_colonne <> NULL ne renvoie aucune ligne, même s'il existe des valeurs non nulles dans nom_colonne.
Par exemple
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 !
Si vous définissez ANSI NULLS OFF, NULL = NULL retournera la comparaison. PAR EXEMPLE :
SET ANSI_NULLS OFF
select * from sys.tables
where principal_id = Null
retournera un résultat tel qu'indiqué ci-dessous: zcwInvoiceDeliveryType 744547 NULL zcExpenseRptStatusTrack 2099048 NULL ZCVendorPermissions 2840564 NULL ZCWOrgLevelClientFee 4322525 NULL
Bien que cette requête ne renvoie aucun résultat:
SET ANSI_NULLS ON
select * from sys.tables
where principal_id = Null