Soru Eksik verileri temsil etmek için NULL yerine standart 'Z' kullanımı?


NULL'lerin kullanılmasının gerekip gerekmediği argümanı dışında: "Eksik veya hiç girilmemiş" anlamına gelen NULL kullanan bir veri tabanından sorumluyum. Boş bir dizgeden farklıdır, yani "kullanıcı bu değeri ayarlamış ve" boş "olarak seçilmiştir.

Projedeki bir başka müteahhit, “NULL'lar benim için mevcut değil; NULL'ı asla kullanmıyorum ve hiç kimsenin tartışmasız tarafı olmamalı”. Ancak, beni şaşırtan şey ise, yüklenicinin ekibi DOES'in "eksik / hiç girilmemiş" ve "bilerek boş veya kullanıcı tarafından bilinmeyen olarak gösterilmesi" arasındaki farkı bilmesidir. Kodları boyunca tek bir karakter 'Z' kullanırlar ve Veritabanının geri kalanı boyunca NULL ile aynı anlamı taşıyan "eksik / hiç girilmemiş" ifadesini temsil eder.

Paylaşılan müşterimiz bunun değişmesini istemesine ve bu talebi desteklememe rağmen, ekip bunu DBA'lardan çok daha ileri düzeydeki "standart uygulama" olarak niteliyor; Sadece cahilce isteğime dayanarak NULL'ları kullanmak için değiştirmek istemiyorlar. Yani, benim cehaletimin üstesinden gelmeme yardım eden var mı? SQL uzmanları arasında NULL yerine 'Z' kullanımını savunan herhangi bir standart ya da küçük bir grup birey ya da tek bir sesli ses var mı?

Güncelleştirme

Yükleniciden eklemek için bir yanıtım var. Müşteri, veri içermeyen sütunlarda NULL'a izin verecek özel değerlerin kaldırılmasını istediğinde şunları söyledi:

Temel olarak, mümkün olduğunda NULL'lerden kaçınmak için veritabanını tasarladım. Gerekçe şu:

Dize [VARCHAR] alanında bir NULL hiçbir zaman gerekli değildir, çünkü boş (sıfır uzunlukta) bir dizi aynı bilgiyi verir.

Bir tamsayı alanındaki bir NULL (ör., Bir ID değeri), verilerde asla oluşmayacak bir değer kullanılarak işlenebilir (ör. Tamsayı IDENTITY alanı için -1). 

Bir tarih alanındaki bir NULL, tarih hesaplamalarında kolayca komplikasyonlara neden olabilir. Örneğin, [RecoveryDate] ile [OnsetDate] arasındaki günlerdeki fark gibi tarih farklarını hesaplayan mantıkta, her iki tarih için açık bir ödeme yapılmadığı sürece mantık, bir veya iki tarihin NULL olması durumunda patlar NULL olmak. Bu ekstra çalışma ve ekstra kullanım. [RecoveryDate] ve [OnsetDate] (örneğin, "1/1/1900") için "default" veya "placeholder" tarihleri ​​kullanılırsa, matematiksel hesaplamalar "olağandışı" değerler gösterebilir - ancak tarih mantığı patlamaz.

NULL işleme geleneksel olarak geliştiricilerin saklı yordamlarda hata yaptıkları bir alan olmuştur. 

15 yıllık bir DBA olarak, mümkün olan her yerde NULL'lerden kaçınmanın en iyisini buldum.

Bu, bu soruna çoğunlukla olumsuz tepkiyi doğrulamaktadır. NULL'leri tasarlarken kabul edilen bir 6NF yaklaşımı uygulamak yerine, "mümkün olan yerlerde NULL'lerden kaçınmak" için özel değerler kullanılır. Bu soruyu açık bir akılla yayınladım ve "NULL'lar yararlı / NULL'lar kötülük" tartışması hakkında daha çok şey öğrendiğime sevindim, fakat artık 'özel değerler' yaklaşımını tam anlamıyla saçmalamak için oldukça konforluyuz.

boş (sıfır uzunluk) bir dizi, tam olarak aynı bilgileri verir.

Hayır, değil; mevcut veritabanında değiştiriyoruz, NULL "hiç girilmemiş" ve boş dize "boş olarak girilmiş" anlamına gelir.

NULL işleme geleneksel olarak geliştiricilerin saklı yordamlarda hata yaptıkları bir alan olmuştur.

Evet, ancak bu hatalar binlerce geliştirici tarafından binlerce kez yapıldı ve bu hatalardan kaçınmak için dersler ve uyarılar biliniyor ve belgeleniyor. Burada belirtildiği gibi: NULL'ları kabul edip etmemeniz, eksik değerlerin temsilidir. çözülmüş problem. Yeni bir çözüm bulmaya gerek yok, çünkü geliştiriciler kolay anlaşılır (ve kolay anlaşılır) hatalar yapmaya devam ediyorlar.


Dipnot olarak: 20 yıldan fazla bir süredir DBE ve geliştirici oldum (ki bu da bir veritabanı mühendisi ve veritabanı yöneticisi arasındaki farkı bilmem için yeterli zaman). Kariyeri boyunca çok sayıda akıllı insanın aynı fikirde olmadığını fark etsem de, her zaman "NULL'lar yararlıdır" kampında bulundum. “Özel değerler” yaklaşımı konusunda son derece şüpheciydim, ama “Doğru NULL'ı Nasıl Yapmalı” başlıklı akademisyenlere sağlam bir duruş sergilemeye yetecek kadar iyi yetişmemiştim. Her zaman yeni şeyler öğrenmeyi seviyorum - ve 20 yıl sonra öğrenecek çok şeyim var. Bunu yararlı bir tartışma yapmaya katkıda bulunan herkese teşekkürler.


76
2017-07-09 23:59


Menşei


Etkinleştirmek için NULL var üçlü mantık Tam bilgi yokluğunda referans bütünlüğünü korumak için gerekli olan - kendilerine karşı kararlı bir şekilde iddia edilen herhangi bir DB uzmanına tam ve kesin BS'yi çağırırım! - gordy
Bu uygulamayı hiç duymadım. - Calvin Allen
Yüklenici, sayısal veriler için de bir NULL vekili teklif etti mi? - Andriy M
@Andriy: Bunu çözmek çok kolay, tüm uzmanlar sayıları karakter alanlarında saklar ve gerektiğinde (Z-kontrolleri ile!) Yayınlar. Bekle, Yanlış yerdeyim. - mu is too short
Bir keresinde, bu yüklenicinin icra etmeye çalıştığından şüpheleniyorum WHERE Column = NULLve neden hiç sonuç almadığı konusunda kafam karışmıştı. - Mike Caron


Cevaplar:


Yükleniciyi çuvalla.

Tamam, cidden, bu standart bir uygulama değil. NULL, NULL için mantık, NULL için mantık ile çalıştığım tüm RDBMS, çünkü yabancı anahtarlarda NULL hesabını, COUNT, vb, vb NULL için farklı davranış var çünkü bu görülebilir

Aslında 'Z' ya da başka bir yer tutucu kullanmanın daha kötü olduğunu iddia ediyorum. Hala 'Z' kontrol etmek için kod gerekiyor. Ama aynı zamanda 'Z' nin 'Z' anlamına gelmediğini, başka bir şey anlamına geldiğini belgelemeniz gerekiyor. Ve bu belgelerin okunduğundan emin olmalısınız. Ve sonra 'Z' geçerli bir veri parçası haline gelirse ne olur? (Bir başlangıç ​​için alan gibi mi?)

Temel düzeyde, NULL ve “Z” nin geçerliliğini tartışmasa bile, yüklenicinin kendi şirketinizde var olan standart uygulamalara uymadığı konusunda ısrar ediyorum. Standart uygulamalarını alternatif bir standart uygulama ile bir ortamda oluşturmak, karışıklığa, bakım giderlerine, yanlış anlaşılmaya ve sonuçta maliyet ve hataların artmasına neden olacaktır.


DÜZENLE

NULL'a alternatif kullanmanın benim görüşüme göre geçerli olduğu durumlar var. Ancak, yalnızca bunu yaparken kodları, muhasebe gerektiren özel durumlar oluşturmaktan ziyade azaltır.

Örneğin, tarihe bağlı veri için kullandım. Veriler, bir başlangıç ​​tarihi ile bir bitiş tarihi arasında geçerliyse, NULL değerleri olmamak kaydıyla kod basitleştirilebilir. Bunun yerine NULL başlangıç ​​tarihi '01 Ocak 1900 'ile değiştirilebilir ve NULL bitiş tarihi '31 Dec 2079' ile değiştirilebilir.

Bu hala beklenen davranışları değiştirebilir ve bu nedenle dikkatli kullanılmalıdır:

  • WHERE end-date IS NULL artık geçerli olan veriyi artık vermeyin
  • Sadece kendi binyıl hatasını yarattın
  • vb.

Bu, tüm özelliklerin her zaman geçerli değerlere sahip olabileceği şekilde soyutlamaları yeniden biçimlendirmekle eşdeğerdir. Özel anlamı örtük olarak keyfi olarak seçilen değerlere kodlamaktan belirgin şekilde farklıdır.

Yine de, yükleniciyi çuvalla.


104
2017-07-10 00:13



Benden +1; spot: "Z 'veya diğer herhangi bir yer tutucu kullanarak daha kötü olduğunu iddia ediyorum. Hala' Z 'için kontrol etmek için kod gerekiyor. Ama aynı zamanda' Z '' Z 'anlamına gelmez. Başka bir şey anlamına geliyor. " - Mitch Wheat
İhtiyacımız olan şey NULL değil, NULL değil, özel bir değerdir - eksik verileri temsil etmek için. Diğer tüm değerlerden farklı bir şey, belki de belki de (çünkü, iki bilinmez, bilinmediklerinden dolayı eşit olamaz). Bazı sütunlar açıkça bu değerle mantıklı olmaz ve bu yüzden yasaklanmalıdır. İşleri kolaylaştırmak için IS UNKNOWN veya IS NOT UNKNOWN gibi özel operatörlere ihtiyacımız var. - Mike Caron
+1 - sihirli değerler NULL'lerden daha kötü. - APC
Müteahhitler genellikle derin deneyimlerden iyi tavsiyelerde bulunurlar. ara sıra olur, tavsiye edilen tehlikeli uçurumun üzerinde koyunları takip etmeniz gerektiği anlamına gelmez. Veritabanının ana ve sahibi olduğunuzu bildirin: geliştirme belirtildiği gibi olacaktır: uymak veya ölmek. - wallyk
Bir kullanıcı Z girerse, o zaman ZZ'yi saklarsınız. ZZ'ye girerlerse, ZZZ'yi vb. Saklarsınız. Bu, tüm sütunlarınızı bir karakter daha büyük yapmanızı gerektirir, ancak bu bir sorun olmamalıdır. - Chas. Owens


Bu, duyduğum en tuhaf fikirlerden biri. NULL yerine "veri yok" u temsil etmek için sihirli bir değer kullanmak, sahip olduğunuz her kod parçasının "no-data" / "Z" değerlerini hesaba / hesaba katmak için sonuçları işlemek zorunda kalacağı anlamına gelir.

NULL, veritabanının sorgularda işleyiş biçimi nedeniyle özeldir. Örneğin, şu iki basit soruyu ele alın:

select * from mytable where name = 'bob';
select * from mytable where name != 'bob';

Eğer name NULL oldu, kesinlikle ilk sorgudaki sonuçlarda görünmeyecek. Daha da önemlisi, ikinci sorgular sonuçlarında da görünmeyecek. NULL, şu şekilde olduğu gibi NULL için açık bir arama dışında bir şeyle eşleşmiyor:

select * from mytable where name is NULL;

Ve veriler geçerli bir değer olarak Z'ye sahip olduğunda ne olur? Diyelim ki birisinin orta ilkini mi saklıyorsun? Zachary Z Zonkas, ortada bir başlangıç ​​yapmamış insanlarla birlikte mi toplanacak? Yoksa yükleniciniz bunu halletmek için başka bir büyü değeriyle mi geliyor?

Veritabanının veritabanını zaten tam olarak kullanabileceği kodda veritabanı özelliklerini uygulamanızı gerektiren sihirli değerlerden kaçının. Bu, çözülmüş ve iyi anlaşılmış bir sorundur ve yüklenicinizin NULL kavramını asla kestirmemesi ve dolayısıyla onu kullanmasını engellememesi olabilir.


26
2017-07-10 00:24





Etki alanı eksik değerlere izin veriyorsa, 'undefined' ifadesini göstermek için NULL kullanmanız tamamen uygun olur (işte tam olarak budur). Tek dezavantajı, NULL'leri kontrol etmek için verileri tüketen kodun yazılması gerektiğidir. Her zaman böyle yaptım.

Eksik verileri temsil etmek için 'Z' kullanımını hiç duymadım (ya da pratikte görmedim). “Yüklenici bunu DBA'lar arasında 'standart uygulama' olarak nitelendiriyor” diye sorarsa, bu iddiaya ilişkin bazı kanıtlar sağlayabilir mi? @Dems'in bahsettiği gibi, 'Z' nin 'Z' anlamına gelmediğini de belgelemeniz gerekir: MiddleInitial Sütun?

Sevmek Aaron Alton ve diğerleri, NULL değerlerinin veritabanı tasarımının ayrılmaz bir parçası olduğuna inanıyorum ve uygun olduğunda kullanılmalıdır.


22
2017-07-10 00:05



+1: Güzel link :) [Hala yükleniciyi çuvalladım.] - MatBailie
Burada anahtarın "alanın kayıp değerlere izin vermesi ..." olduğunu düşünüyorum. Bana NULL'ların kullanımını ve onları esirgemenin bir zaman ve mekanı olan bir zaman ve yer olduğunu düşünüyorum ve bu biraz bilgelik gerektiriyor farkı bilmek. Bir genç DBE / DBA, "NULL değerleri, davranışlarını hesaba katmazsanız, sorgularda ve hesaplamalarda beklenmedik sonuçlara neden olabilir" gibi bir uyarı okuduğunda bazen de duygularını anlarım. Kötü Bir kez dindar bir fikir haline geldiğinde, kariyerinin geri kalanı için onunla yapışır. - Boris Nikolaevich
WHERE yan tümcesini bir DELETE veya UPDATE üzerinde unutmak veritabanınıza zarar verebilir => bunları asla kullanmayın. Verileri ilk seferde doğru yapın ya da bir editörde masayı açın ve kendiniz yapın. - MatBailie
Z bazı standartlarda GMT zaman dilimini temsil etmek için kullanılır. - Erick Robertson
@Erick, bu Z'yi kullanmamak için bir neden daha yok "değer yok" - Boris Nikolaevich


NULL yerine, NULL yerine "Z" hakkındaki tüm güncel ve gelecekteki geliştiricilerinize ve DBA'larınıza açıklamayı başarabilseniz bile, ve her şeyi mükemmel bir şekilde kodlasa bile, optimizasyonu yapan kişiyi karıştırmaya devam edersiniz, çünkü bu işlemi yaptığınızı bilmezsiniz. .

NULL'ı (NULL'ı temsil eden özel bir değer olan) temsil etmek için özel bir değer kullanmak, verilerde çarpıklıklarla sonuçlanır. Örneğin. 1 Ocak-1900'de pek çok şey, optimizatörün, uygulamanızla gerçekten alakalı olan gerçek tarih aralığını anlama yeteneğini ortaya çıkaracak olmasıdır.

Bu bir yönetici gibi karar veriyor: "Bir kravat giymek üretkenlik için kötüdür, bu yüzden hepimiz boyunlarımızda maskeleme bandı kullanacağız. Problem çözüldü."


17
2017-07-10 01:46



+1 ifadesi için sadece "NULL (zaten NULL temsil etmek için özel bir değer) temsil etmek için özel bir değer kullanma". . . - Mike Sherrill 'Cat Recall'
Bir papyonun tam olarak böyle olduğunu düşünmüştüm, o zaman için daha uygun maskeleme bandıyla değiştirilen bir boyun kravat ... - Soren


Yaygın kullanımı hakkında hiç duymadım 'Z' yerine geçmek NULL.

(Bu arada, özellikle siz ve diğer "gelişmiş" DBA'ların sizden çok daha bilgili ve daha iyi olduklarını söyleyen bir yüklenici ile çalışmak istemem.)

 +=================================+
 |  FavoriteLetters                |
 +=================================+
 |  Person      |  FavoriteLetter  |
 +--------------+------------------+
 |  'Anna'      |  'A'             |
 |  'Bob'       |  'B'             |
 |  'Claire'    |  'C'             |
 |  'Zaphod'    |  'Z'             |
 +---------------------------------+

Yükleniciniz son satırdaki verileri nasıl yorumluyor?

Muhtemelen gerçek verilerle çarpışmayı önlemek için bu tabloda farklı bir "büyü değeri" seçecekti. 'Z'? Birkaç sihir değerini hatırlamanız gereken anlamı ve aynı zamanda hangisinin kullanıldığı ... Bu sadece bir sihir jetonundan daha iyi nasıl NULLve onunla birlikte gelen üç değerli mantık kurallarını (ve tuzakları) hatırlamak zorunda mı? NULL Yüklenicinizin aksine en azından standarttır. 'Z'.

Özellikle sevmiyorum NULL Ya da, akılsızca gerçek bir değerle (veya birkaç gerçek değerle daha kötüsü) ikame ederek her yerde neredeyse kesinlikle daha kötü NULL.

Daha iyi bir görünürlük için yukarıdaki yorumumu tekrar edeyim: Eğer karşı olan insanlar tarafından ciddi ve iyi bir şey okumak istiyorsanız NULLKısa makaleyi tavsiye ederim "NULL kullanmadan eksik bilgi nasıl ele alınır" (bir PDF'den bağlantı Üçüncü Manifesto ana sayfası).


9
2017-07-10 09:16





Prensipte hiçbir şey doğru veri tabanı tasarımı için null gerektirmez. Aslında, null kullanmadan tasarlanan birçok veri tabanı var ve veri tabanları kullanmadan veritabanları tasarlayan çok iyi bir çok veritabanı tasarımcıları ve tüm geliştirme ekipleri var. Genel olarak, bir veritabanına null'ların eklenmesi konusunda ihtiyatlı olmak iyi bir şeydir çünkü kaçınılmaz olarak daha sonra yanlış veya belirsiz sonuçlara yol açarlar.

“Standart uygulama” olarak adlandırılan Z'yi boş değer yerine bir yer tutucu değeri olarak kullanmayı duymadım ama yüklenicinizin sentinel değerleri Genel olarak, bazen veritabanı tasarımında kullanılır. Bununla birlikte, "kukla" verileri kullanmadan null'lardan kaçınmanın çok daha yaygın ve esnek bir yolu, bunları tasarlamaktır. Tabloyu, her bir gerçek türün "fazladan", belirtilmemiş özniteliklere sahip olmayan bir tabloya kaydedileceği şekilde ayrıştırın.


4
2017-07-10 07:24



Yüklenicinin kelimenin tam anlamıyla “bilmiyorum” için “bilmiyorum” anlamına geldiğini düşünüyorum. - wallyk
Ne yazık ki, @wallyk temelde doğrudur: bu akademik ya da teorik bir tartışma değildir; Ben kendim geliştirici olduğum için, kod ve saklı yordamlar aracılığıyla olmuştur. Yüklenici, eksik / girilmemiş değerler için 'Z' karakterini kullanıyor. (Aslında, bilinmeyen fakat cevaplanan değerler, mevcut veritabanı tasarımında bile NULL değildir; her ikisi de metin alanları için boş bir dize veya kullanıcının bu soruyu cevapladığını göstermek için açılan liste için "U" karakterini kullanır. ve cevap "Bilmiyorum" idi. - Boris Nikolaevich
@dportas - Doğru veritabanı tasarımının null kullanımını gerektirmediğini biliyorum, ancak "Doğru şekilde nasıl yapılacağını biliyorsanız NULL kullanmak için bir yer ve bir yer var" olduğundan beri soru, "ZN" nin "NoNULL" kampının iyi bir veri tabanı tasarımında kullanılmasının, standart, ortak veya herkes tarafından desteklenip desteklenmediğini anlamaktı. - Boris Nikolaevich


Yüklenicilerin yorumlarına cevap olarak

  • Boş dize <> NULL
  • Boş dize 2 bayt depolama + bir ofset okuması gerektirir
  • NULL null bitmap = daha hızlı kullanır
  • IDENTITY her zaman 1'de başlamıyor (neden menzilinizin yarısını boşa harcıyorsunuz?)

Bütün kavram burada diğer cevapların çoğuna göre hatalı


3
2017-07-12 09:09



Olmasına rağmen; Hatırladığım kadarıyla boş bir ip olduğu Oracle'da NULL. - MatBailie