Що означає в SQL Server “ВСТАНОВИТИ ANSI_NULLS ON”?


92

Визначення говорить:

Коли SET ANSI_NULLS УВІМКНЕНО, оператор SELECT, який використовує WHERE column_name = NULL, повертає нуль рядків, навіть якщо в імені стовпця є нульові значення. Оператор SELECT, який використовує WHERE ім'я_столбця <> NULL, повертає нуль рядків, навіть якщо в імені_столбця є ненульові значення.

Чи означає це, що в цей запит не буде включено нульових значень?

SELECT Region
FROM employees
WHERE Region = @region

Або це ANSI_NULLстосується лише таких запитів, як цей (де WHEREвключає конкретне слово NULL)?

SELECT Region
FROM employees
WHERE Region = NULL

1
Чи немає відповіді вже в 4-му абзаці офіційної документації, з якого ви скопіювали 1-й абзац, а саме: -> "ВСТАНОВИТИ ANSI_NULLS ON впливає на порівняння, лише якщо один з операндів порівняння є або змінною, яка має значення NULL або буквальний NULL. Якщо обидві сторони порівняння - це стовпці або складені вирази, параметр не впливає на порівняння. "
user1451111

Відповіді:


68

Це означає, що при використанні у вашому першому прикладі не буде повернено рядків, якщо @regionє NULL, навіть якщо в таблиці є рядки, де Regionє NULL.

Коли ANSI_NULLSввімкнено (що ви повинні завжди встановлювати в будь-якому випадку, оскільки опція не мати його буде видалена в майбутньому), будь-яка операція порівняння, де (принаймні) один з операндів NULLвиробляє третє логічне значення - UNKNOWN( на відміну від TRUEі FALSE).

UNKNOWNзначення поширюються через будь-які комбінуючі логічні оператори, якщо вони ще не визначені (наприклад, ANDз FALSEоперандом або ORз TRUEоперандом) або запереченнями ( NOT).

WHEREПропозиція використовується для фільтрації результуючого набору , отриманого з допомогою FROMпункту, таким чином, щоб загальна величина WHEREп повинна бути TRUEдля рядка , щоб не бути відфільтровані. Отже, якщо за UNKNOWNрезультатами будь-якого порівняння отримано значення an , це призведе до фільтрування рядка.


@ User1227804 в відповідь включає цю цитату:

Якщо обидві сторони порівняння - це стовпці або складені вирази, параметр не впливає на порівняння.

від *SET ANSI_NULLS

Однак я не впевнений, який момент він намагається зробити, оскільки якщо NULLпорівнювати два стовпці (наприклад, в a JOIN), порівняння все одно не вдається:

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

Наведений вище запит повертає 0 рядків, тоді як:

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)

Повертає один рядок. Отже, навіть коли обидва операнди є стовпцями, NULLне дорівнює NULL. І документація для= не має нічого сказати про операнди:

Коли ви порівнюєте два NULLвирази, результат залежить від ANSI_NULLSналаштування:

Якщо ANSI_NULLSвстановлено значення ON, результат дорівнює NULL1 , дотримуючись положення ANSI, що NULL(або невідоме) значення не дорівнює іншому NULLабо невідомому значенню.

Якщо ANSI_NULLSвстановлено значення OFF, результат NULLпорівняння з NULLє TRUE.

Порівняння NULLз нецінністю NULLзавжди призводить до FALSE2 .

Однак і 1, і 2 є неправильними - результат обох порівнянь є UNKNOWN.


* Таємниче значення цього тексту було остаточно виявлено роками пізніше. Це насправді означає, що для цих порівнянь параметр не має ефекту, і він завжди діє так, ніби параметр увімкнений . Було б зрозуміліше, якби там було зазначено, що SET ANSI_NULLS OFFце обстановка не мала ніякого впливу.


1
отже, якщо я правильно вас розумію: це також впливає на результат фрази "Where Region = @region", а не лише тоді, коли я пишу спеціально "Where Region = null"?
Родніко

7

Якщо @Regionце не nullзначення (скажімо @Region = 'South'), воно не поверне рядки, де поле Регіон є нульовим, незалежно від значення ANSI_NULLS.

ANSI_NULLS буде мати значення лише тоді, коли значення @Regionє null, тобто коли ваш перший запит по суті стає другим.

У цьому випадку ANSI_NULLS ON не поверне жодних рядків (оскільки null = nullвидасть невідоме булеве значення (aka null)), а ANSI_NULLS OFF поверне будь-які рядки, де поле Регіон є нульовим (оскільки null = nullдасть true)


6

Якщо для ANSI_NULLS встановлено значення "ON" і якщо ми застосовуємо =, <> для значення стовпця NULL під час написання оператора select, то це не поверне жодного результату.

Приклад

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

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

ВСТАНОВИТИ 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)

ВСТАНОВИТИ 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 за те, що ЄДИНА відповідь, яка чітко розрізняє WHERE X IS NULLі WHERE X = NULL, і те, як ANSI_NULLS впливає на результат. Незважаючи на надто ревні спроби виборців, ЦЕ має бути прийнятою відповіддю!
Рігардт Штейн

1
+1 за пояснення на прикладах, які завжди будуть чіткішими та коротшими, а не довгими реченнями.
peter.aryanto

3

ВСТАНОВИТИ ANSI_NULLS

IT повертає всі значення, включаючи нульові значення в таблиці

SET ANSI_NULLS вимкнено

він закінчується, коли стовпці містять нульові значення


2
Що додатково додає ця відповідь до вже викладених відповідей? Будьте обережні, додаючи нові відповіді на старі запитання - Вони повинні містити розширені пояснення щодо вже розміщених рішень, або надавати нове розуміння - З огляду
Takarii

1

Думаю, головне тут:

Ніколи користувач:

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

Завжди використовуйте:

  • @anything IS NULL
  • @anything IS NOT NULL

0

Якщо встановити значення ANSI NULLS OFF, порівняння NULL = NULL повернеться істинним. Наприклад:

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

поверне деякий результат, як показано нижче: zcwInvoiceDeliveryType 744547 NULL zcExpenseRptStatusTrack 2099048 NULL ZCVendorPermissions 2840564 NULL ZCWOrgLevelClientFee 4322525 NULL

Хоча цей запит не дасть результатів:

        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

Коли SET ANSI_NULLS УВІМКНЕНО, оператор SELECT, який використовує WHERE column_name = NULL, повертає нуль рядків, навіть якщо в імені стовпця є нульові значення. Оператор SELECT, який використовує WHERE ім'я_столбця <> NULL, повертає нуль рядків, навіть якщо в імені_столбця є ненульові значення.

Наприклад,

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 !
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.