Boolean Field di Oracle

145

Kemarin saya ingin menambahkan bidang boolean ke tabel Oracle. Namun, sebenarnya tidak ada tipe data boolean di Oracle. Apakah ada orang di sini yang tahu cara terbaik untuk mensimulasikan boolean? Googling subjek menemukan beberapa pendekatan

  1. Gunakan bilangan bulat dan jangan repot-repot menetapkan selain dari 0 atau 1 untuk itu.

  2. Gunakan bidang char dengan 'Y' atau 'N' sebagai dua nilai saja.

  3. Gunakan enum dengan batasan PERIKSA.

Apakah pengembang Oracle yang berpengalaman tahu pendekatan mana yang lebih disukai / kanonik?

Eli Courtwright
sumber
195
Saya berharap Oracle memiliki walltipe data sehingga saya bisa menghancurkan kepala saya saat menggunakan boolean.
Greg

Jawaban:

82

Saya menemukan tautan ini bermanfaat.

Berikut adalah paragraf yang menyoroti beberapa pro / kontra dari setiap pendekatan.

Desain yang paling umum dilihat adalah meniru banyak flag seperti Boolean yang digunakan kamus data Oracle, memilih 'Y' untuk true dan 'N' untuk false. Namun, untuk berinteraksi dengan benar dengan lingkungan host, seperti JDBC, OCCI, dan lingkungan pemrograman lainnya, lebih baik untuk memilih 0 untuk false dan 1 untuk true sehingga dapat bekerja dengan benar dengan fungsi getBoolean dan setBoolean.

Pada dasarnya mereka menganjurkan metode nomor 2, demi efisiensi, menggunakan

  • nilai 0/1 (karena interoperabilitas dengan JDBC getBoolean()dll) dengan kendala cek
  • sebuah jenis dari CHAR (karena menggunakan ruang kurang dari NUMBER).

Contoh mereka:

create table tbool (bool char check (bool in (0,1));
insert into tbool values(0);
insert into tbool values(1);`
ColinYounger
sumber
31
Saya menyarankan agar tidak menggunakan 'N' dan 'Y' karena ini tergantung pada bahasa. Anglophones kadang-kadang lupa bahwa sebagian besar dunia tidak mewakili konsep kebenaran dengan huruf Y. Sebaliknya, makna 0 dan 1 konstan di seluruh hambatan bahasa.
Andrew Spencer
7
0 dan 1 sebagai nilai boolean tidak konsisten dalam ilmu komputer - bahasa jenis skrip shell cenderung memiliki 0 sebagai keberhasilan, dan bukan nol sebagai kegagalan, sedangkan bahasa tipe C cenderung memiliki 0 sebagai kegagalan, dan bukan nol sebagai sukses.
Phil
41
Sebagai nilai boolean , mereka tidak ambigu. Kode pengembalian proses bukan nilai boolean.
Andrew Spencer
13
Mengapa seluruh paragraf dari tautan yang disediakan ini diabaikan dalam jawaban ini? "Desain yang paling umum dilihat adalah meniru banyak flag seperti Boolean yang digunakan oleh kamus data Oracle, memilih 'Y' untuk true dan 'N' untuk false. Namun, untuk berinteraksi dengan benar dengan lingkungan host, seperti JDBC, OCCI, dan lingkungan pemrograman lainnya, lebih baik untuk memilih 0 untuk false dan 1 untuk true sehingga dapat bekerja dengan benar dengan fungsi getBoolean dan setBoolean. " Mereka menyatakan bahwa sementara 'Y / N' adalah umum, menggunakan '0/1' untuk meningkatkan kompatibilitas dengan lingkungan host dianjurkan.
justin.hughey
28

Oracle sendiri menggunakan Y / N untuk nilai Boolean. Untuk kelengkapan harus dicatat bahwa pl / sql memiliki tipe boolean, hanya tabel yang tidak.

Jika Anda menggunakan bidang untuk menunjukkan apakah catatan perlu diproses atau tidak, Anda dapat mempertimbangkan menggunakan Y dan NULL sebagai nilai. Ini menghasilkan indeks sangat kecil (baca cepat) yang hanya membutuhkan sedikit ruang.

Leigh Riffel
sumber
7
+1 Poin bagus tentang tampilan internal Oracle dan tabel menggunakan Y / N. Jika Oracle melakukannya dengan cara seperti itu, itu pasti benar! :)
Jeffrey Kemp
Bisakah Anda menjelaskan bagaimana Y dan NULL membuat indeks kecil dibandingkan dengan Y dan N?
styfle
6
NULLs tidak diindeks di Oracle, jadi jika indeks Anda berisi beberapa karakter Y, tetapi sebagian besar NULLs Anda akan memiliki indeks yang sangat kecil.
Leigh Riffel
25

Untuk menggunakan jumlah ruang paling sedikit, Anda harus menggunakan bidang CHAR terbatas ke 'Y' atau 'N'. Oracle tidak mendukung tipe data BOOLEAN, BIT, atau TINYINT, jadi satu byte CHAR sekecil yang Anda bisa dapatkan.

Bill the Lizard
sumber
19

Pilihan terbaik adalah 0 dan 1 (sebagai angka - jawaban lain menunjukkan 0 dan 1 sebagai CHAR untuk efisiensi ruang tapi itu agak terlalu bengkok bagi saya), menggunakan BUKAN NULL dan batasan periksa untuk membatasi konten ke nilai-nilai tersebut. (Jika Anda ingin kolom menjadi nullable, maka itu bukan boolean yang Anda hadapi tetapi enumerasi dengan tiga nilai ...)

Keuntungan 0/1:

  • Bahasa independen. 'Y' dan 'N' akan baik-baik saja jika semua orang menggunakannya. Tetapi mereka tidak melakukannya. Di Perancis mereka menggunakan 'O' dan 'N' (saya telah melihat ini dengan mata kepala sendiri). Saya belum memprogram di Finlandia untuk melihat apakah mereka menggunakan 'E' dan 'K' di sana - tidak diragukan lagi mereka lebih pintar dari itu, tetapi Anda tidak bisa memastikan.
  • Sejalan dengan praktik dalam bahasa pemrograman yang banyak digunakan (C, C ++, Perl, Javascript)
  • Dimainkan lebih baik dengan lapisan aplikasi misalnya Hibernate
  • Mengarah ke SQL yang lebih ringkas, misalnya, untuk mencari tahu berapa banyak pisang yang siap dimakan select sum(is_ripe) from bananasalih-alih select count(*) from bananas where is_ripe = 'Y'atau bahkan (yuk)select sum(case is_ripe when 'Y' then 1 else 0) from bananas

Keuntungan dari 'Y' / 'N':

  • Memakan ruang kurang dari 0/1
  • Itulah yang disarankan Oracle, jadi mungkin beberapa orang lebih terbiasa

Poster lain menyarankan 'Y' / null untuk keuntungan kinerja. Jika Anda telah membuktikan bahwa Anda membutuhkan kinerja, maka cukup adil, tetapi jika tidak hindari karena membuat kueri kurang alami (dan some_column is nullbukannya some_column = 0) dan di gabung kiri Anda akan menyalahartikan kepalsuan dengan catatan yang tidak ada.

Andrew Spencer
sumber
3
Anda menemukan bahwa hari ini banyak Boolean adalah TriState yaitu benar, salah dan tidak dikenal. yang sangat cocok dengan ide nol database. hanya karena banyak kali mengetahui tidak ada jawaban yang diberikan adalah sangat penting
MikeT
1
Ya, benar-salah-tidak diketahui bisa diperlukan, meskipun jika saya pilih-pilih (yang saya), saya akan mengatakan itu seharusnya tidak benar-benar digambarkan sebagai Boolean, karena tidak.
Andrew Spencer
2
jika Anda akan pilih-pilih itu maka Anda dapat membuat argumen yang sama untuk setiap tipe data. seperti di bawah integer definisi yang ketat, ganda (saya kira saya harus mengatakan dua panjang ganda floating point), Biner, string, dll. Semua menganggap nilai diberikan tetapi implementasi basis data selalu menambahkan opsi nilai nol Boolean tidak berbeda
MikeT
1
benar, pada catatan plus untuk metode Anda jika Anda mengkonfigurasi nomor Anda dengan benar, itu juga dapat disimpan dalam byte tunggal yang sama sebagai bidang char, yang membatalkan argumen ukuran terhadap penggunaan 0/1, saya tidak dapat menemukan tautan saat ini tetapi penyimpanan untuk jumlah berkisar dari 1 - 22 byte tergantung pada konfigurasi
MikeT
4
Saya menduga downvotes adalah karena sudut pandang lama dalam memilih implementasi memori yang paling efisien. Efisiensi memori hari ini dan usia jauh dari prioritas dan harus diperhitungkan setelah kegunaan dan kompatibilitas. Bagi siapa saja yang dapat menanggapi komentar ini, saya sarankan membaca tentang pengoptimalan prematur. Itulah yang terjadi dengan memilih 'Y / N' murni berdasarkan efisiensi memori. Anda kehilangan kompatibilitas asli dengan satu set kerangka kerja yang umum digunakan karena keputusan itu.
justin.hughey
5

Baik 1/0 atau Y / N dengan batasan cek di atasnya. cara eter baik-baik saja. Saya pribadi lebih suka 1/0 karena saya banyak bekerja di perl, dan itu membuatnya sangat mudah untuk melakukan operasi perl Boolean di bidang basis data.

Jika Anda ingin diskusi yang sangat mendalam tentang pertanyaan ini dengan salah satu kepala honorer Oracles, lihat apa yang dikatakan Tom Kyte tentang ini Di Sini

Matthew Watson
sumber
1/0 dikatakan "kurang efisien memori" tapi ... Saya lebih menyukainya (dan hibernate tampaknya membutuhkan 1/0 untuk boolean)
rogerdpack
1/0 adalah standar Hibernate untuk boolean tetapi Anda dapat menentukan pemetaan kustom apa pun yang Anda suka.
Andrew Spencer
@rogerdpack thats karena bidang char adalah 1 byte, atau 2 byte untuk nchar, di mana tergantung bagaimana didefinisikan, sebuah Number bisa 1 hingga 22 byte
MikeT
4

Basis data yang saya lakukan sebagian besar pekerjaan saya menggunakan 'Y' / 'N' sebagai boolean. Dengan implementasi itu, Anda dapat melakukan beberapa trik seperti:

  1. Hitung baris yang benar:
    SELECT SUM (KASUS KETIKA BOOLEAN_FLAG = 'Y' KEMUDIAN 1 LAIN 0) DARI X

  2. Saat mengelompokkan baris,
    jalankan logika "Jika satu baris benar, maka semuanya benar" logika: SELECT MAX (BOOLEAN_FLAG) DARI Y
    Sebaliknya, gunakan MIN untuk memaksa pengelompokan itu salah jika satu baris salah.

Erick B
sumber
4
sebenarnya contoh yang ditampilkan juga berguna untuk pendekatan 0/1 - dan, IMHO, lebih cepat.
igorsantos07
2

Contoh yang berfungsi untuk mengimplementasikan jawaban yang diterima dengan menambahkan kolom "Boolean" ke tabel yang ada di database oracle (menggunakan numbertipe):

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))
);

Ini menciptakan kolom baru yang my_table_namedisebut my_new_boolean_columndengan nilai default 0. Kolom tidak akan menerima NULLnilai dan membatasi nilai yang diterima baik 0atau 1.

Ben.12
sumber
1

Dalam basis data kami, kami menggunakan enum yang memastikan kami memberikannya BENAR atau SALAH. Jika Anda melakukannya salah satu dari dua cara pertama, terlalu mudah untuk mulai menambahkan makna baru ke integer tanpa melalui desain yang tepat, atau berakhir dengan bidang char yang memiliki Y, y, N, n, T, t, t, F, f menghargai dan harus mengingat bagian kode mana yang menggunakan tabel mana dan versi mana yang benar yang digunakannya.

Ryan Ahearn
sumber