Eşit değil <>! = NULL üzerinde operatör


271

Birisi SQL'de aşağıdaki davranışı açıklayabilir mi?

SELECT * FROM MyTable WHERE MyColumn != NULL (0 Results)
SELECT * FROM MyTable WHERE MyColumn <> NULL (0 Results)
SELECT * FROM MyTable WHERE MyColumn IS NOT NULL (568 Results)

Yanıtlar:


309

<>Standart SQL-92'dir; !=eşdeğeridir. Her ikisi NULLde değil , değerlerin değerlendirilmesi - NULLbir değerin yok olduğunu söylemek için bir yer tutucudur.

Bu nedenle , bu gibi durumlar için IS NULL/ IS NOT NULLolarak yalnızca tahmin olarak kullanabilirsiniz .

Bu davranış, SQL Server'a özgü değildir. Tüm standartlara uygun SQL lehçeleri aynı şekilde çalışır.

Not : En eğer karşılaştırmak değeri boş değil , kullanmak IS NOT NULLile karşılaştırmak ise, değil boş değer, kullanmak <> 'YOUR_VALUE'. Değerimin NULL değerine eşit olup olmadığını söyleyemem, ancak değerimin NULL olup olmadığını söyleyebilirim. Değerimin NULL dışında bir şey olup olmadığını karşılaştırabilirim.


4
Aslında, <>92 spesifikasyonda olduğuna inanıyorum, ancak çoğu satıcı destekliyor !=ve / veya 99 veya 03 gibi daha sonraki bir spesifikasyona dahil ediliyor.
Thomas

2
@Thomas: Oracle !=anladığım kadarıyla ~ 9i'ye kadar desteklemedi , bu da birçok ANSI-92 sözdizimi getirdi. Benim inancım MySQL benzer, 4.x desteğe başlıyor.
OMG Ponies

Bu, !=daha sonraki bir spesifikasyona alternatif olarak dahil edilmiş olabileceğini düşündürmektedir <>. Yeni özellikler üzerinde ellerim yok, bu yüzden kesin olarak söyleyemem.
Thomas

2
Sonuç mu WHERE MyColumn != NULLyoksa WHERE MyColumn = NULLdeterministik mi? Ya da başka bir deyişle, MyColumnveritabanında nullable olsun ya da olmasın , her zaman 0 satır döndürmesi garanti edilir mi?
Slauma

11
Ayrıca, !=yalnızca değerleri değerlendirdiğinden, böyle bir şey yapmanın WHERE MyColumn != 'somevalue'NULL kayıtları döndürmeyeceği de belirtilmelidir.
jsumrall

88

NULL değeri yoktur ve bu nedenle skaler değer işleçleri kullanılarak karşılaştırılamaz.

Başka bir deyişle, hiçbir değer NULL değerine eşit olamaz (veya eşit değildir), çünkü NULL değeri yoktur.

Bu nedenle, SQL özel IS NULL ve IS NOT NULL NULL ile ilgili tahmin eder.


3
+1. Ve OP deyiminin aksine, bu "Microsoft SQL" değildir. Trinary mantığı SQL Standardında tanımlanır ve MS bu noktada standarda uyar.
TomTom

6
Bunun yalnızca Microsoft'a özgü bir davranış olduğunu öne sürmüyordum. Sadece Microsoft SQL Server'da gözlemlediğimi söylüyordum.
Maxim Gershkovich

13
İlgisiz, bu (beklenen) davranışın yararlı olduğu durumlar var mı? Sadece 'a' != nullbir değer ( true/ 1) döndürmüyor olması bana karşı sezgisel ve zaman zaman beni yakalar gibi görünüyor ! Ben "değeri olmayan bir değer" her zaman "eşit değil" olacağını düşünürdüm, ama belki bu sadece ben?!?
DarthPablo

1
İnsanların NULL'u ' değersiz ' olarak tanımlamaları ilginç . Benzer şekilde, aslında bir değer olduğunda 1 sayısının 'bir değeri olduğunu' söylemek de benzerdir. Ama NULL değeri olmayan temsil eder ..
systemaddict

El ile bir geçici çözüm olarak, genellikle SELECT * FROM MyTable WHERE coalesce(MyColumn, 'x') <> 'x'NULL değeriyse bir sabit atayabilirsiniz, böylece sentinel değeri x için uygun bir veri türü (bu durumda bir dize / karakter) verebilirsiniz. Bu TSQL sözdizimidir, ancak Oracle ve diğer motorlar benzer özelliklere sahiptir.
systemaddict

26

Bu davranışın varsayılan (ANSI) davranış olduğunu unutmayın.

Eğer sen:

 SET ANSI_NULLS OFF

http://msdn.microsoft.com/en-us/library/ms188048.aspx

Farklı sonuçlar elde edersiniz.

SET ANSI_NULLS OFF Görünüşe göre gelecekte gidecek ...


8
+1 ... yakında değil. Şimdi ne zaman bir dizinde "yinelenen" NULL alabilirim? :(

Filtrelenmiş bir dizine bir WHERE deyimi ekleyerek bir SQL Server dizininde yinelenen NULL'ler alabilirsiniz (örn. create unique index UK_MyTable on MyTable (Column) where Column is not null): Msdn.microsoft.com/en-us/library/cc280372.aspx
Anthony Mills

3
Dokümanlardan Not: Ne zaman SET ANSI_NULLSKAPALI, Eşittir (=) ve Not Eşittir (<>) karşılaştırma operatörleri ISO standardı takip etmezler. Kullanan bir SELECT deyimi, WHERE column_name = NULLsütun_adı içinde null değerleri olan satırları döndürür. Kullanan bir SELECT deyimi WHERE column_name <> NULL, sütunda boş olmayan değerlere sahip satırları döndürür. Ayrıca, kullanan bir SELECT deyimi WHERE column_name <> XYZ_valueXYZ_value olmayan ve NULL olmayan tüm satırları döndürür. IMHO, bu son ifade null'ların sonuçlardan çıkarılmasında biraz tuhaf görünüyor!
DarthPablo

4
Msdn doc'den önemli not : SQL Server'ın gelecekteki bir sürümünde [2014'ten daha yeni], ANSI_NULLS her zaman AÇIK olur ve seçeneği açıkça KAPALI olarak ayarlayan uygulamalar bir hata oluşturur. Bu özelliği yeni geliştirme çalışmalarında kullanmaktan kaçının ve şu anda bu özelliği kullanan uygulamaları değiştirmeyi planlayın.
Otiel

7

SQL'de, NULLsonuçları değerlendirdiğiniz / hesapladığınız her şey BİLİNMEYEN

Bu yüzden SELECT * FROM MyTable WHERE MyColumn != NULLya SELECT * FROM MyTable WHERE MyColumn <> NULLda size 0 sonuç verir.

NULLDeğerlerin kontrolü için isNull işlevi sağlanmıştır.

Ayrıca, ISüçüncü sorguda kullandığınız gibi işleci kullanabilirsiniz .

Bu yardımcı olur umarım.


Msgstr "SQL'de, NULL sonuçlarıyla değerlendirdiğiniz / hesapladığınız her şey 'NULL' içine" - yanlış Demek istediğin sonuç BİLİNMİYOR.
oneday14

@MahendraLiya isNull işlevi NULLS değerini denetlemek için sağlanmamıştır, ancak " NULL değerini belirtilen değiştirme değeriyle değiştirir. " Farklı bir şey olan ISNULL yerine IS NULL veya IS NOT NULL kullanmalısınız.
Ters Mühendis


6

Kullanırız

SELECT * FROM MyTable WHERE ISNULL(MyColumn, ' ') = ' ';

MyColumn'un NULL olduğu tüm satırları veya MyColumn'un boş bir dize olduğu tüm satırları döndürmek için. Birçok "son kullanıcı" için, NULL ve boş dize sorunu, ihtiyaç ve karışıklık noktası olmayan bir ayrımdır.


5

Boş değerlerin diğer değerlerle veya boş değerlerle karşılaştırılamaz olmasının işlevsel ve kesintisiz nedenini görmüyorum, çünkü bunu açıkça karşılaştırabiliyor ve bağlamımızda aynı ya da değil olduklarını söyleyebiliriz. Komik. Sadece bazı mantıklı sonuçlar ve tutarlılık nedeniyle bununla sürekli uğraşmamız gerekiyor. İşlevsel değil, daha işlevsel hale getirin ve tutarlı olup olmadığına ve "evrensel mantık" a sahip olup olmadığına karar vermek için filozoflara ve bilim adamlarına bırakın. :) Birisi bunun indeksler ya da başka bir şey yüzünden olduğunu söyleyebilir, bu şeylerin değerlerle aynı null'ları desteklemek için yapılamadığından şüpheliyim. İki boş bardağı karşılaştırmakla aynı, biri asma cam, diğeri bira camı, nesne türlerini karşılaştırmıyoruz, ancak içerdikleri değerleri int ve varchar ile karşılaştırabileceğiniz gibi null ile karşılaştırıyoruz ' daha da kolay, hiçbir şey ve iki hiçliğin ortak noktası nedir, onlar aynı, ben ve sql yazan herkes tarafından açıkça karşılaştırılabilir, çünkü bazı ANSI standartları nedeniyle onları garip yollarla karşılaştırarak sürekli olarak bu mantığı kırıyoruz. Neden bizim için bunu yapmak için bilgisayar gücünü kullanmıyorsunuz ve ilgili her şey akılda tutulursa işleri yavaşlatacağından şüpheliyim. "Boş değil, hiçbir şey değil", elma değil apfel, hadi ... İşlevsel olarak arkadaşın ve burada da mantık var. Sonuçta önemli olan işlevselliktir ve null'ları bu şekilde kullanmak az ya da çok işlevsellik ve kullanım kolaylığı getirir. Daha faydalı mı? çünkü bazı ANSI standartları nedeniyle bu mantığı garip yollarla karşılaştırarak sürekli kırıyoruz. Neden bizim için bunu yapmak için bilgisayar gücünü kullanmıyorsunuz ve ilgili her şey akılda tutulursa işleri yavaşlatacağından şüpheliyim. "Boş değil, hiçbir şey değil", elma değil apfel, hadi ... İşlevsel olarak arkadaşın ve burada da mantık var. Sonuçta önemli olan işlevselliktir ve null'ları bu şekilde kullanmak az ya da çok işlevsellik ve kullanım kolaylığı getirir. Daha faydalı mı? çünkü bazı ANSI standartları nedeniyle bu mantığı garip yollarla karşılaştırarak sürekli kırıyoruz. Neden bizim için bunu yapmak için bilgisayar gücünü kullanmıyorsunuz ve ilgili her şey akılda tutulursa işleri yavaşlatacağından şüpheliyim. "Boş değil, hiçbir şey değil", elma değil apfel, hadi ... İşlevsel olarak arkadaşın ve burada da mantık var. Sonuçta önemli olan işlevselliktir ve null'ları bu şekilde kullanmak az ya da çok işlevsellik ve kullanım kolaylığı getirir. Daha faydalı mı? elma değil apfel, hadi ... İşlevsel olarak arkadaşın ve burada da bir mantık var. Sonuçta önemli olan işlevselliktir ve null'ları bu şekilde kullanmak az ya da çok işlevsellik ve kullanım kolaylığı getirir. Daha faydalı mı? elma değil apfel, hadi ... İşlevsel olarak arkadaşın ve burada da bir mantık var. Sonuçta önemli olan işlevselliktir ve null'ları bu şekilde kullanmak az ya da çok işlevsellik ve kullanım kolaylığı getirir. Daha faydalı mı?

Bu kodu düşünün:

SELECT CASE WHEN NOT (1 = null or (1 is null and null is null)) THEN 1 ELSE 0 end

Kaçınız bu kodun ne getireceğini biliyor? NOT ile veya NOT olmadan 0 döndürür. Bana göre bu fonksiyonel değildir ve kafa karıştırıcı. C # 'de olması gerektiği gibi, karşılaştırma işlemleri değer döndürür, mantıksal olarak bu da değer üretir, çünkü eğer yoksa karşılaştırılacak hiçbir şey yoktur (hiçbir şey hariç). Onlar sadece "dediler": null "ile karşılaştırıldığında" 0 "döndürürler ve bu da birçok geçici çözüm ve baş ağrısı oluşturur.

Beni buraya getiren kod:

where a != b OR (a is null and b IS not null) OR (a IS not null and b IS null)

Sadece iki alanda (nerede) farklı değerler varsa karşılaştırmak gerekir, işlev kullanabilirsiniz, ama ...


4

NULL Karşılaştırma işleçleri kullanılarak herhangi bir değerle karşılaştırılamaz. NULL = NULL yanlış. Null bir değer değil. IS operatörü, NULL karşılaştırmaları işlemek için özel olarak tasarlanmıştır.


5
Bazen bazı geçici sorgularda kullanabileceği null = nullyerlerde kullandığımda her zaman şaşkın insanlardan keyif aldım 1=0. Ve şikayet ederse, bunu null != null:) olarak değiştiririm
SWeko

8
"NULL = NULL yanlış" Bu öyle değil. NULL = NULL, bilinmeyen olarak değerlendirilir ve yanlış değil.
nvogel

@dportas öyle ama demek istediğim şartlı olarak doğru olarak değerlendirilmeyecek.
Vincent Ramdhanie

@VincentRamdhanie ne yanlış; aslında, Postgres'e içinde NULL olarak değerlendirilecektir
Pere

2

Eski bir soru, ancak aşağıdakiler biraz daha ayrıntı verebilir.

nullhiçbir değeri veya bilinmeyen bir değeri temsil eder. Neden bazı belirsizlikler doğurabilecek bir değer olmadığını belirtmez .

Diyelim ki böyle bir sorgu çalıştırıyorsunuz:

SELECT *
FROM orders
WHERE delivered=ordered;

yani orderedve deliveredtarihlerinin aynı olduğu satırları arıyorsunuz .

Bir veya iki sütun boş olduğunda ne beklenir?

Tarihlerden en az biri bilinmiyor olduğundan, 2 tarihin aynı olduğunu söyleyemezsiniz. Bu, her iki tarihin de bilinmediği durumdur : ne olduklarını bilmiyorsak bile nasıl olabilirler?

Bu nedenle, nulldeğer olarak davranan herhangi bir ifade başarısız olmalıdır. Bu durumda, eşleşmez. Aşağıdakileri denerseniz bu da geçerlidir:

SELECT *
FROM orders
WHERE delivered<>ordered;

Yine, nasıl iki değer olduğunu söyleyebiliriz değil ne olduklarını bilmiyorsanız aynı.

SQL'in eksik değerler için belirli bir testi vardır:

IS NULL

Özellikle değerleri karşılaştırmak değil , eksik değerleri arar .

Son olarak, !=operatör ile ilgili olarak, bildiğim kadarıyla, aslında standartların hiçbirinde değildir, ancak çok geniş bir şekilde desteklenmektedir. Bazı dillerdeki programcıların kendilerini evlerinde daha fazla hissetmelerini sağlamak için eklendi. Açıkçası, bir programcı hangi dili kullandıklarını hatırlamakta zorlanıyorsa, kötü bir başlangıç ​​yapıyorlar.


Bu @Hove'un cevabında tanımladığı aynı "saçma" "mantık" tır. Gerçek şu ki, bu bağlamda bu fazladan gereçlere ihtiyaç yoktur; bir şeyi bir NULLile karşılaştırdığımızda, değeri bir NULLdeğerin " bir değere sahip" ile karşılaştırdığımızı , değeri "alt öğenin NULL¿sahip olduğu belirsiz değere ?" değil, "ki bunu kesinlikle bilemeyiz. Bu gerçekten işleri kolaylaştırır.
Pere

@ Kesinlikle “saçma” olduğunu söylemezdim ve yazmanın yazmaktan IS NULLçok daha zahmetli olduğundan emin değilim = NULL. Bence , ikincisine özel bir durum olarak davranmak yerine WHERE columnA = columnB, aynı yorumda bulunmanın daha tutarlı olacağını düşünüyorum WHERE columnA = NULL. Unutmayın NULLolduğu değil bir değer. O programlama dilleri olarak ise test etmek için meşru variable == nullçünkü öyle nullfarklı bir anlamı vardır; bilinmeyen bir şeyi değil, bir değerin kasıtlı olarak sıfırlanmasını temsil eder. SQL ile öyle değil.
Manngo

Bu yüzden tırnak işaretleri arasına koydum, @Mangoo;) (ve ayrıca "mantık"). Bana kızma; ANSI "muhakeme" den bahsediyordum, açıklamanızdan değil. Son örneğinizde IS NULLAND =NULLarasında ek yük olmadığına katılıyorum . Ama Hover'ın sonuncusuna bir bakın. Tekrar tekrar deneyimlemekten bıktım, bir sürü of gereksiz yapmak zorunda mıyım? ekstra kontrol ...
Pere

1

Her ne kadar (sipariş önemli olmasa da) iyeni bir değer dolmak ve eski olmak bir değerde bir değişiklik olup olmadığını bulmak için yapılan bu kodu önermek istiyorum . Bu nedenle, değerden null'a veya tersi bir değişiklik bir değişikliktir, ancak null'den null'e (elbette, değerden başka bir değere bir değişikliktir, değerden aynı değildir).

CREATE FUNCTION [dbo].[ufn_equal_with_nulls]
(
    @i sql_variant,
    @d sql_variant
)
RETURNS bit
AS
BEGIN
    DECLARE @in bit = 0, @dn bit = 0
    if @i is null set @in = 1
    if @d is null set @dn = 1

    if @in <> @dn
        return 0

    if @in = 1 and @dn = 1
        return 1

    if @in = 0 and @dn = 0 and @i = @d
        return 1

    return 0

END

Bu işlevi kullanmak için şunları yapabilirsiniz:

declare @tmp table (a int, b int)
insert into @tmp values
(1,1),
(1,2),
(1,null),
(null,1),
(null,null)

---- in select ----
select *, [dbo].[ufn_equal_with_nulls](a,b) as [=] from @tmp

---- where equal ----
select *,'equal' as [Predicate] from @tmp where  [dbo].[ufn_equal_with_nulls](a,b) = 1

---- where not equal ----
select *,'not equal' as [Predicate] from @tmp where  [dbo].[ufn_equal_with_nulls](a,b) = 0

Sonuçlar:

---- in select ----
a   b   =
1   1   1
1   2   0
1   NULL    0
NULL    1   0
NULL    NULL    1

---- where equal ----
1   1   equal
NULL    NULL    equal

---- where not equal ----
1   2   not equal
1   NULL    not equal
NULL    1   not equal

Sql_variant kullanımı onu çeşitli tipler için uyumlu hale getirir


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.