Oracle 9i neden boş bir dizeyi NULL olarak değerlendiriyor?


216

Ben bunu bilmek gelmez olarak '' dikkate NULLama söylemek için çok yapmaz neden bu böyledir. SQL spesifikasyonlarını anladığım gibi, '' ile aynı değil NULL- biri geçerli bir veri ve diğeri aynı bilginin yokluğunu gösteriyor.

Spekülasyon yapmaktan çekinmeyin, ancak lütfen durumun bu olup olmadığını belirtin. Oracle'dan yorum yapabilen biri varsa, bu harika olurdu!


9
Spekülasyon yapmaktan çekinmeyin? Her nasılsa bu size en büyük cevapları sağlayacak sanmıyorum ..
SCdF

1
Sanmıyorum, ama konuyla ilgili herhangi bir kesinlik olduğundan emin değildim, bu yüzden kapıları açacağımı düşündüm. Şimdiye kadar iyi çalışmış gibi görünüyor.
Chris R


Yanıtlar:


216

Cevabın Oracle'ın çok, çok eski olduğuna inanıyorum.

Geri SQL standardı hiç uğramadan Eski günlerde de Oracle boş dizeleri tasarım kararı VARCHAR/ VARCHAR2sütunlar vardı NULLve NULL yalnızca bir anlam olduğunu (istenirse olmamıştı veriler arasında ayrım olur ilişkisel teorisyenler vardır, yanıtın var olduğu ancak kullanıcı tarafından bilinmediği veriler, yanıtın olmadığı veriler vb. hepsi bir anlam ifade eder NULL).

SQL standardı geldiğinde ve NULLboş dizenin farklı varlıklar olduğunu kabul ettiğinde, ikisinin eşdeğer olduğunu varsayan kodları olan Oracle kullanıcıları zaten vardı. Böylece Oracle temel olarak mevcut kodu kırma, SQL standardını ihlal etme veya potansiyel olarak çok sayıda sorgunun işlevselliğini değiştirecek bir tür başlatma parametresi sunma seçenekleriyle kaldı. SQL standardını (IMHO) ihlal etmek, bu üç seçenekten en az rahatsız edici olanıydı.

Oracle, VARCHARSQL standardına uymak için gelecekteki bir sürümde veri türünün değişme olasılığını açık bıraktı (bu nedenle VARCHAR2, veri türünün davranışının aynı kalması garanti edildiği için herkes Oracle'da kullanıyor ).


60

Tom Kyte Oracle Başkan Yardımcısı:

Bir SIFIR uzunluklu varchar NULL olarak kabul edilir.

'', NULL olarak değerlendirilmez.

'' bir karaktere (1) atandığında '' olur (karakter türleri boş dolgulu dizelerdir).

'' varchar2 (1) 'e atandığında sıfır uzunluklu bir dize olan' 'olur ve Oracle'da sıfır uzunluklu bir dize NULL olur (uzun değildir' ')


17
Vay canına, Tom oldukça sinsi. Soruların SQL92'den gelen korkunç bir sapma ile ilgili olduğu göz önüne alındığında, cevap vermekten yorulmuş olsa da, bunun hakkında daha az yumruklu olacağını düşünürdünüz.
Chris R

8
Tom hakkında en iyi şey, tam olarak ne düşündüğünü belirten net bir cevap almanızdır. İnsanların metin kullandıkları bazı sorulara bakın Ask Tom
Chris Gill hakkında

9
Ancak ikinci satırın ''
ypercubeᵀᴹ

2
@ypercube Alıntı, Tom tarafından kullanılan kelimeyi değiştirerek kesinleşmiyor. Tom'un kafa karıştırıcı bir şekilde ifade ettiğini düşünüyorsanız, mmm. Olabilir. Bence yerinde . Zaman en kafa karıştırıcı durumlar ortaya ''ediliyor metotunun bir VARCHAR2, dönüştürülen gibi cast('' as char(1)) is nullolan ... şaşırtıcı DOĞRU
sehe

1
@sehe benim için kafa karıştırıcı bit ikili 'den 1' seçin ('' boş)
matt freake

20

Oracle'ı, daha önceki geliştiricilerin muhtemelen böyle bir veri giriş sistemi için yüceltilmiş bir arka uç olarak düşünürseniz, bunun çok daha mantıklı olduğundan şüpheleniyorum. Veritabanındaki her alan, veri giriş operatörünün ekranında gördüğü formdaki bir alana karşılık geldi. Operatör bir alana herhangi bir şey yazmadıysa, "doğum tarihi" veya "adres" olsun, o alandaki veriler "bilinmiyor" olur. Bir operatörün birinin adresinin gerçekten boş bir dize olduğunu ve bunun gerçekten bir anlamı olmadığını belirtmesi mümkün değildir.


5
Bu, yalnızca bir veri giriş sistemindeki her alanın zorunlu olduğunu varsayarsanız mantıklıdır. Zorunlu olmayan bir alana (örn. "Köpeğin Adı") yanıt verilmemesi geçerlidir, bu nedenle boş bir dize NULL'dan farklı bir amaca sahiptir. Bu varsayımla bile, erken geliştiricilerin Oracle'ı bir "veri giriş sistemi için yüceltilmiş arka uç" olarak düşündüğünden şüpheliyim, bu yüzden bu cevabın hiç mantıklı olmadığından emin değilim.
Jared

19

Oracle belgeleri, geliştiricileri bu sorunla ilgili olarak en azından sürüm 7'ye kadar geri bildirir.

Oracle, "imkansız değer" tekniği ile NULLS'u temsil etmeyi seçti. Örneğin, sayısal bir konumdaki bir NULL, imkansız bir değer olan "eksi sıfır" olarak depolanacaktır. Hesaplamalardan kaynaklanan tüm sıfırlar depolanmadan önce pozitif sıfıra dönüştürülecektir.

Oracle ayrıca sıfır uzunluğundaki VARCHAR dizesini (boş dize) imkansız bir değer ve NULL'ı temsil etmek için uygun bir seçenek olarak düşünmeyi de seçti. Boş dizenin imkansız bir değerden uzak olduğu ortaya çıkıyor. Hatta dize birleştirme işlemi altında bile kimlik!

Oracle belgeleri, veritabanı tasarımcıları ve geliştiricileri, Oracle'ın gelecekteki bazı sürümlerinin boş dize ve NULL arasındaki bu ilişkiyi kırabileceği ve bu ilişkilendirmeye bağlı olan herhangi bir kodu kırabileceği konusunda uyarır.

NULLS'ı imkansız değerler dışında işaretleme teknikleri vardır, ancak Oracle bunları kullanmamıştır.

(Bir satır ve bir sütunun kesişimini ifade etmek için yukarıdaki "konum" kelimesini kullanıyorum.)


Oracle belgeleri, veritabanı tasarımcıları ve geliştiricileri, Oracle'ın gelecekteki bazı sürümlerinin boş dize ve NULL arasındaki bu ilişkiyi kırabileceği ve bu ilişkilendirmeye bağlı herhangi bir kodu kırabileceği konusunda uyarır - lütfen bu ifade için referans sağlayabilir misiniz?
Piotr Dobrogost


2

Boş dize NULL ile aynıdır, çünkü iki (boş dize ve null) aynı olmadığında durumla karşılaştırıldığında onun "küçük kötülük "'ü.

NULL ve boş Dize'nin aynı olmadığı dillerde, her zaman her iki durumu da kontrol etmek gerekir.


Sütununuza not nullkısıtlama getirin ve yalnızca boş dizeyi kontrol edin.
Egor Skriptunoff

6
Her iki koşulu da kontrol etmek önemsizdir: WHERE Field <> ''yalnızca alan NULL değilse ve boş değilse, boş dizeler için ANSI davranışı olan veritabanlarında true değerini döndürür.

1

Resmi 11g belgelerine göre

Oracle Database, şu anda sıfır uzunluğu olan bir karakter değerini null olarak kabul eder. Ancak, bu, gelecekteki sürümlerde geçerli olmaya devam edebilir ve Oracle, boş dizelere boş değerlerle aynı davranmamanızı önerir.

Olası nedenler

  1. val IS NOT NULL daha okunabilir val != ''
  2. Her iki koşulu da kontrol etmeye gerek yok val != '' and val IS NOT NULL

5
Tamamen ANSI uyumlu bir veritabanında, her iki koşulu da kontrol etmeniz gerekmez. val <> ''zaten hariç tutulur NULL. Belki demek istedin val = '' OR val IS NULL. Ancak NULL olarak karşılaştırılmayan boş dizeler yararlıdır !
ErikE

Karşılaştırma kısmına katılıyorum.
Sıralayıcı

0

Kitaptan örnek

   set serveroutput on;   
    DECLARE
    empty_varchar2 VARCHAR2(10) := '';
    empty_char CHAR(10) := '';
    BEGIN
    IF empty_varchar2 IS NULL THEN
    DBMS_OUTPUT.PUT_LINE('empty_varchar2 is NULL');
    END IF;


    IF '' IS NULL THEN
    DBMS_OUTPUT.PUT_LINE(''''' is NULL');
    END IF;

    IF empty_char IS NULL THEN
    DBMS_OUTPUT.PUT_LINE('empty_char is NULL');
    ELSIF empty_char IS NOT NULL THEN
    DBMS_OUTPUT.PUT_LINE('empty_char is NOT NULL');
    END IF;

    END;

-1

Çünkü NULL olarak davranmamak da çok yardımcı olmuyor.

Oracle'ın bu alanında bir hata yaparsanız, genellikle hemen fark edersiniz. Bununla birlikte, SQL sunucusunda çalışıyor gibi görünecek ve sorun yalnızca birisi NULL yerine boş bir dize girdiğinde (belki de null öğesinin "" değerinden farklı olduğu bir .net istemci kitaplığından geldiğinde görünür, ancak genellikle aynı davranırsınız) ).

Oracle'ın doğru olduğunu söylemiyorum, ama bana göre her iki yol da yaklaşık olarak aynı derecede kötü.


2
Hata ayıklamak çok, çok daha kolay. Ayrıca, ekranda boş bir hücre veya giriş görürseniz, DB'deki verilerin boş olduğunu bilirsiniz. '' <> NULL olan diğer DB'lerde, verilerin boş olup olmadığını "göremezsiniz" veya "", bu çok sinsi hatalara yol açar. '' = null, standart olmasa bile en kolay seçenektir.
Lucio M. Tato

2
“'' <> NULL olan diğer DB'lerde, verinin null olup olmadığını" göremezsiniz "veya ''" => DB araçları genellikle NULL'ları boş dizelerden farklı görüntüler. Aslında, Oracle SQL Developer bile NULL'ları “(null)” olarak gösterir. Sanırım bu, NULL'u boşluktan ayırmaktır, ancak NULL ve boş dizeler arasındaki farkla ilgisizdir.
Didier L

-6

Aslında, görünüşte bazı buggy aracılığıyla veritabanına eklenmesine izin verilen geçersiz datetime değerleri (yazdırılamaz, dönüştürülemez veya herhangi bir şey, sadece DUMP () işlevi ile bakıldı) dahil olmak üzere Oracle ile uğraşmada zorluklardan başka bir şeyim olmadı. ikili sütun olarak istemcinin sürümü! Veritabanı bütünlüğünü korumak için çok fazla!

NULL bağlantılarının Oracle kullanımı:

http://digitalbush.com/2007/10/27/oracle-9i-null-behavior/

http://jeffkemponoracle.com/2006/02/empty-string-andor-null.html


1
geçersiz veri zamanı değerleri? Bunun ne anlama geldiğinden emin değilim. Buraya bir soru olarak gönderdiniz mi?

1
Önceden birikmiş yığın akışı sorunu - Oracle forumlarından hiçbir yararlı bilgi almadım ve bir geçici çözüm oluşturdum - Notlarımı takip edip buraya göndereceğim.
Cade Roux

Ayrıntılar burada bir soru olarak gönderildi.
Cade Roux

-6

Her şeyden önce, null ve null dize Oracle tarafından her zaman aynı olarak ele alınmadı. Boş bir dize, tanım gereği, karakter içermeyen bir dizedir. Bu hiç de bir boş değildir. NULL, tanım gereği verilerin olmamasıdır.

Beş ya da altı yıl kadar önce, boş karakter dizisi Oracle tarafından boş değerden farklı işlem gördü. Null gibi, null dize her şeye eşit ve her şeyden farklı olsa da (null için iyi olduğunu düşünüyorum, ancak null dize için tamamen YANLIŞ), en azından uzunluk (null dize) boş dize olduğu gibi 0 döndürür sıfır uzunlukta bir dize.

Şu anda Oracle'da, length (null), tamam olduğunu tahmin ettiğim null değerini döndürür, ancak length (null string) de tamamen WRONG olan null değerini döndürür.

Neden bu 2 farklı "değeri" aynı şekilde ele almaya karar verdiklerini anlamıyorum. Farklı şeyler ifade ediyorlar ve programcı her biri üzerinde farklı şekillerde hareket etme yeteneğine sahip olmalı. Metodolojilerini değiştirdikleri gerçeği bana, bu değerlerin nasıl ele alınması gerektiği konusunda gerçekten bir ipucularının olmadığını söylüyor.


"Null string" ve NULL değeri arasında bir ayrım yapmak için alıntı gerekir. Oracle dışındaki herhangi bir veritabanında, bir VARCHARalanın değeri (sıfır veya daha fazla karakter) olabilir veya hiçbir değeri (NULL), tam durdurma olabilir.

2011'den "beş ya da altı yıl önce" 10g zaman dilimine düşecekti (10.1 2003, 10.2 2005'te yayınlanacak). 10g, null'ların işlenmesinde kesinlikle herhangi bir küresel değişiklik getirmedi ve hiçbir zaman NULLve null değerli bir dize arasında herhangi bir ayrım olmamıştır ve böyle bir ayrım mantıklı değildir. Korkarım bu cevap tam bir fantezi.
William Robertson
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.