SQL Server'da "SET ANSI_NULLS ON" ne anlama geliyor?


92

Tanım şöyle diyor:

SET ANSI_NULLS AÇIK olduğunda, WHERE column_name = NULL kullanan bir SELECT ifadesi, sütun_adı içinde boş değerler olsa bile sıfır satır döndürür. WHERE column_name <> NULL kullanan bir SELECT ifadesi, column_name'de boş olmayan değerler olsa bile sıfır satır döndürür.

Bu, bu sorguya boş değerlerin dahil edilmeyeceği anlamına mı geliyor?

SELECT Region
FROM employees
WHERE Region = @region

Yoksa ANSI_NULLyalnızca bunun gibi sorgularla mı ilgileniyor ( WHEREbelirli bir kelimeyi içerdiğinde NULL)?

SELECT Region
FROM employees
WHERE Region = NULL

1
Cevap, 1. paragrafı kopyaladığınız resmi belgenin 4. paragrafında zaten bulunmuyor mu? veya değişmez bir NULL. Karşılaştırmanın her iki tarafı da sütun veya bileşik ifadeyse, ayar karşılaştırmayı etkilemez. "
user1451111

Yanıtlar:


68

Bu takdirde hiçbir satır döndürülür anlamına gelir @regionise NULLilk örnekte kullanılan zaman tabloda satır olduğunda bile, Regionbir NULL.

Ne zaman ANSI_NULLSaçıksa (yine de her zaman ayarlamanız gerekir, çünkü bunu göstermeme seçeneği gelecekte kaldırılacaktır), işlenenlerden birinin (en azından) olduğu herhangi bir karşılaştırma işlemi NULLüçüncü mantık değerini üretir - UNKNOWN( TRUEve FALSE) aksine .

UNKNOWNdeğerler, önceden karar verilmemişse (örneğin ANDbir FALSEişlenenle veya ORbir TRUEişlenenle) veya olumsuzluklarla ( NOT) herhangi bir birleştirici mantıksal işleç yoluyla yayılır .

WHEREMaddesi tarafından üretilen sonuç kümesi filtrelemek için kullanılır FROMmadde, toplam değer, bu WHEREmadde olmalıdır TRUEsatır için filtrelenebilir değil. Dolayısıyla, UNKNOWNherhangi bir karşılaştırma ile üretilirse, satırın filtrelenmesine neden olur.


@ user1227804'ün cevabı şu alıntıyı içerir:

Karşılaştırmanın her iki tarafı da sütun veya bileşik ifadeyse, ayar karşılaştırmayı etkilemez.

itibaren *SET ANSI_NULLS

Bununla birlikte, hangi noktaya gelmeye çalıştığından emin değilim, çünkü iki NULLsütun karşılaştırılırsa (örneğin a'da JOIN), karşılaştırma yine de başarısız olur:

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

Yukarıdaki sorgu 0 satır döndürürken:

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)

Bir satır döndürür. Yani her iki işlenen de sütun olsa bile NULLeşit değildir NULL. Ve dokümantasyonunda= işlenenler hakkında söylenecek hiçbir şey yok:

İki NULLifadeyi karşılaştırdığınızda , sonuç ANSI_NULLSayara bağlıdır :

Olarak ANSI_NULLSayarlanırsa , ANSI kuralına göre, bir (veya bilinmeyen) değerin başka veya bilinmeyen bir değere eşit olmadığı ONsonucu NULL1 olur .NULLNULL

Olarak ANSI_NULLSayarlanmışsa OFF, NULLkarşılaştırmanın sonucu NULLeşittir TRUE.

Değer NULLolmayan ile karşılaştırmak NULLher zaman FALSE2 ile sonuçlanır .

Ancak, her iki 1 ve 2 yanlıştır - her ikisi de karşılaştırmalar sonucudur UNKNOWN.


* Bu metnin şifreli anlamı nihayet yıllar sonra keşfedildi. Gerçekte anlamı, bu karşılaştırmalar için ayarın hiçbir etkisinin olmaması ve her zaman ayar AÇIKmış gibi davranmasıdır . SET ANSI_NULLS OFFHiçbir etkisi olmayan ortam olduğunu belirtmiş olsaydı daha net olurdu .


1
bu yüzden sizi doğru anlıyorsam: "Bölge = @ bölge" ifadesinin sonucunu da etkiler ve yalnızca özellikle "Bölge = null" yazdığımda değil?
Rodniko

7

Değer @Regiondeğilse null(diyelim @Region = 'South'), ANSI_NULLS değerinden bağımsız olarak Bölge alanının boş olduğu satırları döndürmez.

ANSI_NULLS, yalnızca değeri @Regionolduğu nullzaman, yani ilk sorgunuz esasen ikincisi olduğunda bir fark yaratacaktır .

Bu durumda, ANSI_NULLS ON herhangi bir satır döndürmez (çünkü null = nullbilinmeyen bir boole değeri (aka null) verir) ve ANSI_NULLS OFF, Bölge alanının boş olduğu herhangi bir satırı döndürür (çünkü null = nullsonuç verir true)


6

ANSI_NULLS "ON" olarak ayarlanmışsa ve select deyimini yazarken NULL sütun değerine =, <> uygularsak herhangi bir sonuç döndürmeyecektir.

Misal

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

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

ANSI_NULLS AYARLA

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 KAPAT

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 , ve arasındaki farkı WHERE X IS NULLve WHERE X = NULLANSI_NULLS'un sonucu nasıl etkilediğini açıkça ayıran TEK yanıt olduğu için. Aşırı gayretli aşağı seçmenlerin girişimlerine rağmen, BU kabul edilen cevap olmalıdır!
Riegardt Steyn

1
Uzun cümleler yerine her zaman daha net ve daha kısa olacak örnekler kullanarak açıklama için +1.
peter.aryanto

3

ANSI_NULLS AYARLA

BT Tablodaki boş değerler dahil tüm değerleri döndürür

SET ANSI_NULLS kapalı

Sütunlar boş değerler içerdiğinde sona erer


2
Bu cevap, önceden belirtilen cevaplara fazladan ne ekler? Eski sorulara yeni yanıtlar eklemeye karşı dikkatli olun - Bunlar, halihazırda yayınlanan çözümlere ilişkin genişletilmiş açıklamalar içermeli veya yeni bilgiler sağlamalıdır - İncelemeden
Takarii

1

Sanırım buradaki ana şey:

Asla kullanıcı:

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

Her zaman kullan:

  • @anything IS NULL
  • @anything IS NOT NULL

0

ANSI NULLS OFF olarak ayarlamak, NULL = NULL karşılaştırmasının doğru olmasını sağlar. ÖRNEĞİN :

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

aşağıda görüntülendiği gibi bazı sonuçlar döndürecektir: zcwInvoiceDeliveryType 744547 NULL zcExpenseRptStatusTrack 2099048 NULL ZCVendorPermissions 2840564 NULL ZCWOrgLevelClientFee 4322525 NULL

Bu sorgu herhangi bir sonuç döndürmeyecek olsa da:

        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 AÇIK olduğunda, WHERE column_name = NULL kullanan bir SELECT deyimi sütun_adı içinde boş değerler olsa bile sıfır satır döndürür. WHERE column_name <> NULL kullanan bir SELECT ifadesi, column_name içinde boş olmayan değerler olsa bile sıfır satır döndürür.

Örneğin

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 !
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.