Oracle'da Boole Alanı


145

Dün bir Oracle tablosuna bir boole alanı eklemek istedim. Ancak, Oracle'da gerçekte bir boolean veri türü yoktur. Boolean simüle etmenin en iyi yolunu bilen var mı? Konuyu araştırmak birkaç yaklaşım keşfetti

  1. Bir tam sayı kullanın ve ona 0 veya 1 dışında bir şey atama zahmetine girmeyin.

  2. Yalnızca iki değer olarak "Y" veya "N" olan bir karakter alanı kullanın.

  3. CHECK kısıtlaması olan bir enum kullanın.

Deneyimli Oracle geliştiricileri hangi yaklaşımın tercih edildiğini / kurallara uygun olduğunu biliyor mu?


195
Keşke Oracle'ın bir wallveri türü olsaydı, böylelikle booleleri kullanırken kafamı ona karşı parçalayabilirdim.
Greg

Yanıtlar:


82

Bu bağlantıyı faydalı buldum .

İşte her yaklaşımın bazı artılarını / eksilerini vurgulayan paragraf.

En yaygın görülen tasarım, Oracle'ın veri sözlüğü görünümlerinin kullandığı birçok Boole benzeri bayrağı taklit etmektir, doğru için 'Y' ve yanlış için 'N' seçilmektedir. Bununla birlikte, JDBC, OCCI ve diğer programlama ortamları gibi ana bilgisayar ortamlarıyla doğru bir şekilde etkileşim kurmak için, getBoolean ve setBoolean işlevleriyle doğru şekilde çalışabilmesi için false için 0 ve true için 1 seçmek daha iyidir.

Temel olarak, verimlilik uğruna 2 numaralı yöntemi savunuyorlar.

  • 0/1 değerleri (JDBC'ler ile birlikte çalışabilirlik nedeniyle getBoolean()vb.) bir kontrol kısıtlaması ile
  • bir tür CHAR (çünkü NUMBER'dan daha az boşluk kullanır).

Örnekleri:

create table tbool (bool char check (bool in (0,1));
insert into tbool values(0);
insert into tbool values(1);`

31
Dile bağlı olduğu için 'N' ve 'Y' kullanılmamasını tavsiye ederim. Anglofonlar bazen dünyanın büyük bir kısmının hakikat kavramını Y harfiyle temsil etmediğini unutur. Buna karşılık, 0 ve 1'in anlamı dil engelleri boyunca sabittir.
Andrew Spencer

7
Boole değerleri olarak 0 ve 1, bilgisayar bilimi içinde tutarlı değildir - kabuk betiği türü diller, başarı olarak 0 ve başarısızlık olarak sıfır olmayan bir değere sahip olma eğilimindeyken, C türü diller başarısızlık olarak 0 ve başarı olarak sıfırdan farklı olma eğilimindedir.
Phil

41
Gibi boole değerler, bunlar unambigous bulunmaktadır. İşlem dönüş kodları boole değerleri değildir.
Andrew Spencer

13
Verilen bağlantıdaki bu paragrafın tamamı bu yanıtta neden göz ardı edildi? "En yaygın görülen tasarım, Oracle'ın veri sözlüğü görünümlerinin kullandığı Boole benzeri bayrakların çoğunu taklit etmektir, doğru için 'Y' ve yanlış için 'N' seçilmelidir. Bununla birlikte, JDBC, OCCI gibi ana bilgisayar ortamlarıyla doğru etkileşim için ve diğer programlama ortamlarında, yanlış için 0 ve doğru için 1 seçmek daha iyidir, böylece getBoolean ve setBoolean işlevleriyle doğru şekilde çalışabilir. " "E / H" yaygın olmakla birlikte, ana bilgisayar ortamlarıyla uyumluluğu artırmak için "0/1" kullanılmasının önerildiğini belirtirler.
justin.hughey

28

Oracle, Boole değerleri için E / H'yi kullanır. Tamlık için, pl / sql'nin boolean tipine sahip olduğuna dikkat edilmelidir, sadece tablolar yoktur.

Kaydın işlenmesi gerekip gerekmediğini belirtmek için alanı kullanıyorsanız, değerler olarak Y ve NULL kullanmayı düşünebilirsiniz. Bu, çok az yer kaplayan çok küçük (hızlı okuma) bir dizin oluşturur.


7
+1 Oracle dahili görünümleri ve E / H kullanan tablolar hakkında iyi bir nokta. Oracle bunu bu şekilde yaparsa, doğru olmalı! :)
Jeffrey Kemp

Y ve NULL'un Y ve N'ye kıyasla nasıl küçük bir indeks oluşturduğunu açıklayabilir misiniz?
styfle

6
Oracle'da NULL'lar indekslenmez, bu nedenle indeksiniz birkaç Y karakter içeriyorsa, ancak çoğunlukla NULL'lar çok küçük bir indeksiniz olacaktır.
Leigh Riffel

25

En az boşluğu kullanmak için "Y" veya "N" ile sınırlandırılmış bir CHAR alanı kullanmalısınız. Oracle BOOLEAN, BIT veya TINYINT veri türlerini desteklemez, bu nedenle CHAR'ın bir baytı alabileceğiniz kadar küçüktür.


19

En iyi seçenek 0 ve 1'dir (sayı olarak - başka bir cevap, alan verimliliği için CHAR olarak 0 ve 1'i önerir, ancak bu benim için biraz fazla bükülmüş), NOT NULL ve içeriği bu değerlerle sınırlamak için bir kontrol kısıtlaması kullanır. (Sütunun null yapılabilir olması gerekiyorsa, o zaman uğraştığınız bir boole değil, üç değerli bir numaralandırma ...)

0/1 avantajları:

  • Dilden bağımsız. Herkes kullansaydı 'Y' ve 'N' iyi olurdu. Ama yapmıyorlar. Fransa'da 'O' ve 'N' kullanıyorlar (bunu kendi gözlerimle gördüm). Finlandiya'da orada 'E' ve 'K' kullanıp kullanmadıklarını görmek için program yapmadım - şüphesiz bundan daha akıllılar, ama emin olamazsınız.
  • Yaygın olarak kullanılan programlama dillerinde (C, C ++, Perl, Javascript) pratikle uyumlu
  • Uygulama katmanıyla daha iyi oynar, örneğin Hazırda Bekletme
  • Örneğin, kaç muzun, hatta (yuk) select sum(is_ripe) from bananasyerine yemeye hazır olduğunu bulmak için daha kısa ve öz SQL'e select count(*) from bananas where is_ripe = 'Y'götürür.select sum(case is_ripe when 'Y' then 1 else 0) from bananas

"Y" / "N" nin avantajları:

  • 0 / 1'den daha az yer kaplar
  • Oracle'ın önerdiği gibi, bazı insanların daha alışkın olduğu şey de olabilir

Başka bir poster performans kazanımları için 'Y' / null önerdi. Eğer ettiyseniz kanıtlanmış sonra performans, adil yeterli gerekir, ancak daha az doğal (sorgulama yapar beri aksi kaçınmanızı some_column is nullyerine some_column = 0) ve bir sol Eğer varolmayan kayıtlarla sahtelik conflate edeceğiz katılmak.


3
Bu günlerde birçok Booleanın TriState olduğunu, yani doğru, yanlış ve bilinmeyen olduğunu görüyorsunuz. veritabanı boş fikrine mükemmel şekilde uyuyor. çünkü çoğu zaman hiçbir cevabın verilmediğini bilmenin hayati önemi var
MikeT

1
Evet, doğru-yanlış-bilinmeyen gerekli olabilir, ancak seçici olsaydım (ki ben), bunun gerçekten bir Boole olarak tanımlanmaması gerektiğini söyleyebilirim, çünkü öyle değil.
Andrew Spencer

2
o kadar seçici olacaksanız, her veri türü için aynı argümanı yapabilirsiniz. katı tanım tamsayı altında olduğu gibi, double (sanırım çift uzunluklu iki tamamlayıcı kayan nokta demeliyim), Binary, string, vb. hepsi bir değer sağlandığını varsayar, ancak veritabanı uygulamaları her zaman bir boş değer seçeneği ekler Boole farklı değildir
MikeT

1
doğru, yönteminiz için artı bir notta, numaranızı doğru şekilde yapılandırırsanız, aynı zamanda bir karakter alanı ile aynı tek baytta saklanabilir, bu da 0/1 kullanımına karşı boyut bağımsız değişkenini geçersiz kılar, şu anda bağlantıyı bulamıyorum ama yapılandırmaya bağlı olarak 1 - 22 bayt arasında değişen bir sayı için depolama alanı
MikeT

4
Olumsuz oyların, bellek açısından en verimli uygulamayı seçme konusundaki eski bakış açısına bağlı olduğundan şüpheleniyorum. Bu gün ve yaştaki bellek verimliliği çok daha az önceliklidir ve kullanılabilirlik ve uyumluluktan sonra dikkate alınmalıdır. Bu yoruma cevap verebilecek herkese, erken optimizasyon hakkında okumayı tavsiye ederim. Tamamen bellek verimliliğine bağlı olarak "E / H" yi seçerek olan tam olarak budur. Bu karar nedeniyle, yaygın olarak kullanılan bir dizi çerçeveyle yerel uyumluluğu kaybediyorsunuz.
justin.hughey

5

1/0 veya E / H üzerinde bir kontrol kısıtlaması var. eter yolu iyidir. Perl'de bir çok iş yaptığım için şahsen 1 / 0'ı tercih ediyorum ve veritabanı alanlarında perl Boole işlemleri yapmayı gerçekten kolaylaştırıyor.

Bu sorunun gerçekten Oracles baş adamlarından biriyle derinlemesine tartışılmasını istiyorsanız, Tom Kyte'nin bu konu hakkında söylediklerine bir göz atın İşte


1 / 0'ın "daha az bellek verimli" olduğu söyleniyor ama ... Ben de daha çok seviyorum (ve görünüşe göre hazırda bekletme bir boole için 1/0 gerektirir)
rogerdpack

1/0, bir boole için Hazırda Bekletme'nin varsayılanıdır, ancak istediğiniz herhangi bir özel eşlemeyi tanımlayabilirsiniz.
Andrew Spencer

@rogerdpack thats çünkü bir karakter alanı 1 bayt veya nchar için 2 bayttır, burada nasıl tanımlandığına bağlı olarak bir Sayı 1 ila 22 bayt olabilir
MikeT

4

Çalışmamın çoğunu yaptığım veritabanı boolean olarak 'Y' / 'N' kullandı. Bu uygulamayla, aşağıdaki gibi bazı püf noktaları elde edebilirsiniz:

  1. Doğru olan satırları sayın:
    TOPLAMI SEÇİN (BOOLEAN_FLAG OLDUĞUNDA CASE = 'Y' SONRA 1 BAŞKA 1 0)

  2. Satırları gruplandırırken, "Bir satır doğruysa, hepsi doğrudur" mantığını
    zorlayın : Y'den MAKS (BOOLEAN_FLAG) SEÇİN
    Tersine, bir satır yanlışsa yanlış gruplamayı zorlamak için MIN kullanın.


4
aslında gösterilen örnekler 0/1 yaklaşımı için de yararlıdır - ve IMHO, daha hızlıdır.
igorsantos07

2

Bir oracle veritabanındaki mevcut bir tabloya bir "Boole" sütunu ekleyerek kabul edilen yanıtı uygulamak için çalışan bir örnek ( numbertürü kullanarak ):

ALTER TABLE my_table_name ADD (
my_new_boolean_column number(1) DEFAULT 0 NOT NULL
CONSTRAINT my_new_boolean_column CHECK (my_new_boolean_column in (1,0))
);

Bu, varsayılan değerleri 0 olan my_table_nameçağrıda yeni bir sütun oluşturur my_new_boolean_column. Sütun NULLdeğerleri kabul etmez ve kabul edilen değerleri ya 0da ile sınırlar 1.


1

Veritabanlarımızda, DOĞRU veya YANLIŞ olarak geçmemizi sağlayan bir enum kullanıyoruz. İlk iki yoldan birini yaparsanız, ya uygun bir tasarıma geçmeden tamsayıya yeni anlam eklemeye başlamak ya da bu karakter alanı Y, y, N, n, T, t ile bitmek çok kolaydır. F, f değerleri ve kodun hangi bölümünün hangi tabloyu kullandığını ve hangi true sürümünü kullandığını hatırlamak zorunda.

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.