Alasan tidak menggunakan angka nullable di Oracle?

12

Perusahaan kami berinteraksi dengan perusahaan perangkat lunak lain untuk proyek bersama, dan kami diberitahu bahwa, jika nilai tertentu tidak boleh ditampilkan, kami harus memberikan -5000 (nilai sentinel sewenang-wenang mereka); alasannya adalah bahwa tidak ada kolom angka dalam basis data Oracle mereka yang mendukung nilai nol, berdasarkan rekomendasi dari Oracle Dev yang sekarang (sebelumnya). Perusahaan ini juga menulis sebagian besar kode mereka di VB6 (perlahan beralih ke VB.NET, yang merupakan topik lain untuk hari lain ...). Karena penasaran, apakah ada alasan sah untuk rekomendasi ini? Saya tidak bisa memikirkan sisi saya.

--- sunting

Terima kasih atas umpan baliknya semua. Saya mengajukan pertanyaan yang sama pada CodeProject.com ( tautan ) dan menerima umpan balik yang sangat mirip. Tampaknya satu-satunya saat seseorang dapat mulai membenarkan praktik ini terkait dengan kunci asing, dan saya dapat menyatakan bahwa mereka tidak menggunakan kunci asing di mana pun dalam sistem. Pengembang yang membuat tekad ini (saya dulu bekerja di perusahaan itu) memiliki pengalaman yang jauh lebih banyak daripada saya, jadi saya ingin memastikan tidak ada alasan yang sah untuk ini sebelum cemoohan terjadi.

Cade Roux
sumber
2
Maksud Anda, selain "itulah yang ditentukan API mereka"?
Robert Harvey
Ya, saya lebih ingin tahu tentang mengapa API mereka akan menentukan itu di tempat pertama; apakah ada alasan untuk praktik ini, atau ini hanya kegilaan?
3
Imamat dari tatanan tertinggi!
Philᵀᴹ

Jawaban:

17

Secara realistis, persyaratannya gila. Namun, seperti semua ide gila hebat, itu mungkin didasarkan pada nugget potensi kewajaran yang diambil jauh dari konteks oleh orang-orang yang tidak memiliki pemahaman tentang alasan yang mendasarinya.

Masuk akal untuk merancang skema basis data sedemikian rupa sehingga tidak ada NULLnilai yang diizinkan. Namun, jika Anda melakukannya, Anda berkomitmen ke tingkat normalisasi di mana setiap elemen yang tidak diperlukan dipecah menjadi tabel terpisah dengan referensi kunci asing yang sesuai kembali ke induk. Ini tidak sering dilakukan dalam praktek tetapi dalam kasus-kasus di mana masuk akal untuk dilakukan, mungkin ada manfaatnya.

Jika Anda akan merancang skema basis data sedemikian rupa sehingga tidak ada NULLnilai yang diizinkan, tidak masuk akal untuk membiarkan apalagi memerlukan nilai ajaib untuk menunjukkan bahwa ada sesuatu yang tidak diketahui. Itu memperkenalkan semua masalah yang memungkinkan NULLnilai ditambah dan menambahkan kode tambahan untuk memeriksa nilai-nilai ajaib yang harus diulang di semua tempat. Tidak masuk akal untuk mengembangkan API yang membutuhkan nilai ajaib untuk diteruskan terlepas dari desain database - jika Anda akan pincang kode Anda dengan memeriksa nilai-nilai ajaib, Anda benar-benar tidak harus membiarkan kegilaan menyebar ke sistem lain .

Gua Justin
sumber
+1 dan kode tambahan untuk memeriksa nilai ajaib tidak dapat menggunakan fungsi terkenal seperti COALESCE()- jadi ini menjadi lebih rumit.
ypercubeᵀᴹ
Dan nilai-nilai perlu disimpan dalam indeks apa pun pada kolom itu. Indeks tidak harus menyimpan nilai nol.
Tripp Kinetics
15

Tidak Ada Alasan Valid untuk menggunakan nilai ajaib alih-alih NULL. Ini mungkin proses pemikiran seseorang yang menciptakan kekacauan ini. Mereka menulis sesuatu seperti ini:

 SELECT c1, c2 FROM t1 WHERE c3 < 30;

Ketika ini tidak mengembalikan hasil yang mereka harapkan, mereka menyadari bahwa itu tidak termasuk NULL dan harus menulis ini:

SELECT c1, c2 FROM t1 WHERE c3 < 30 OR c3 IS NULL;

Mereka tidak ingin menulis atau lupa di masa depan untuk menulis ini, jadi mereka datang dengan solusi untuk membuat semua NULLS -5000. Ajaibnya permintaan asli mereka menangani NULLs tanpa perubahan apa pun. Apa yang tidak mereka sadari adalah bahwa sekarang seseorang yang ingin mengecualikan nilai-nilai ini harus menulis ini:

SELECT c1, c2 FROM t1 WHERE c3 < 30 AND c3 <> -5000;

Atau jika mereka menginginkan nilai-nilai ini dan sedang mencari rentang yang lebih tinggi:

SELECT c1, c2 FROM t1 WHERE c3 > 40 OR c3 = -5000;

Mereka juga mungkin tidak menyadari bahwa hal-hal berikut tidak lagi bermakna:

SELECT c1, c2 FROM t1 WHERE c3 IS NULL;

Sebaliknya seseorang harus mengingat nilai sihirnya. Dengan setiap datatype yang digunakan, mereka harus mengingat lebih banyak nilai ajaib misal 1/1 // 1900, "Z", -5000. Lebih jauh, ketika nilai ajaib ada dalam data, mereka juga harus mengingat nilai sulap alternatif.

Jadi, untuk satu kasus tertentu itu membuat kode lebih sederhana dengan mengorbankan kasus lain, belum lagi ruang disk, ukuran indeks, penguraian kueri, konsistensi, dll.

Leigh Riffel
sumber
8

Ini benar-benar gila dan tidak ada pembenaran untuk itu. NULLtelah dibuat untuk mewakili tidak adanya nilai & menggunakan nilai aktual seperti -5000 adalah gila.

Biasanya saya tidak akan menulis jawaban sesingkat ini, tetapi pertanyaannya layak menjadi salah satu yang paling terlihat di dba.se & semakin banyak jawaban semakin baik.

Philᵀᴹ
sumber
5

Saya memikirkan hal ini untuk sedikit mencoba menjadi positif dan membenarkan perlunya menggunakan nilai arbitrer alih-alih nol dan sepertinya (bagi saya setidaknya) tidak ada alasan yang sah untuk ini, kecuali mungkin dalam dataset data-mining tertutup untuk meningkatkan dan menyederhanakan kinerja dan kueri, dan kemudian hanya dalam kasus-kasus di mana angka-angka itu bukan nilai-nilai yang mungkin memiringkan data. Bahkan ini harus dipertimbangkan dengan hati-hati. Dalam semua situasi dunia nyata memberikan nilai ke nol bukanlah praktik yang baik. Ini mengubah definisi kolom NOT NULL dari teman Anda menjadi musuh Anda karena itu sebenarnya tidak benar.

Merupakan hal yang sangat berbeda untuk mengatakan bahwa aplikasi kita tidak boleh menerima nilai NULL untuk beberapa (atau bahkan semua) kolom. Ini masuk akal dan praktik yang baik dan ada manfaat yang terdokumentasi dengan baik untuk tidak membiarkan nol (kunci dan indeks dan perhitungan statistik misalnya). Namun, menetapkan nilai untuk "duduk di tempat" nol sama sekali tidak sama. Ini adalah batang untuk punggung Anda sendiri, karena Anda harus terlebih dahulu memilih nilai yang tidak akan pernah digunakan, menyaring nilai ini seperti yang Anda inginkan nol dan ingat untuk tidak menggunakannya dalam perhitungan dan ringkasan dan menghapusnya dari umpan data eksternal . Ini setidaknya sama buruknya dengan menggunakan nol untuk mewakili nilai aktual, yang Anda katakan pada diri sendiri bahwa Anda menghindarinya, tetapi ternyata tidak.

Sebagian besar masalah yang menyebabkan nulls, setelah dipahami, dapat ditangani (normalisasi yang lebih baik, indeks berbasis fungsi atau bitmap atau dengan WHERE x IS NOT NULL). Apakah Anda berpikir bahwa pada beberapa Telco besar atau di Amazon dalam pertemuan kinerja bulanan beberapa DBA menguraikan rencana besar ini untuk mempercepat pertanyaan pada set data besar mereka sedikit "dengan mengganti null dengan nilai arbitrer, sesuatu seperti -5000, atau apa pun - Saya terbuka pada nilai ... ". Atau apakah Anda pikir mereka menghabiskan waktu mereka di antara desain aplikasi yang lebih baik untuk menyaring nol yang tidak diinginkan dan optimasi kueri berdasarkan data aktual yang mereka dapatkan ? OK, boleh saja mungkin rapat bulanan agak optimis, tetapi setiap kali itu terjadi saya dapat meyakinkan Anda bahwa "Mengganti null dengan -5000 (atau apa pun) untuk API yang lebih baik" bukan merupakan agenda.

Bagi saya tidak apa-apa untuk mengatakan bahwa saya tidak akan menerima data yang hilang (Anda harus memiliki usia atau harga atau kode wilayah atau apa pun) dan kadang-kadang bahkan baik untuk mengatakan untuk kolom ini ada nilai default yang akan dimasukkan jika Anda tidak menaruh sesuatu yang lain. Tidaklah baik untuk menyisihkan nilai berarti nol. Pikirkan bidang nama tengah sebagai contoh. Kadang-kadang ini tidak akan ada karena orang tua terlalu malas untuk mengisi semua kotak. Apakah kami menambahkan "tidak ada" atau "tidak ada" atau "tidak dikenal" ke data kami untuk meningkatkan pencarian kami? Tidak karena mungkin ada orang aneh yang mengubah nama mereka menjadi nilai-nilai ini dan ketika kita mencetak data, kita tidak tahu apakah kita harus memasukkannya atau tidak. Ini adalah contoh sederhana, tetapi jauh jangkauannya. Kami tahu tentang NULL dan memiliki fungsi bawaan yang dapat diprediksi untuk menghadapinya. Anda tidak dapat membuat kode ini lebih baik.

Jika tidak ada jawaban (atau NULL) bukan respons yang valid untuk permintaan input Anda maka jangan izinkan dalam aplikasi atau dalam database, jika itu merupakan respons yang baik maka Anda harus mengizinkannya di aplikasi dan database Anda dan berurusan dengan itu sebagai respons yang valid. Jika itu adalah bagian dari serangkaian tanggapan yang valid, database Anda harus dirancang untuk menyimpannya. Lagipula Anda tidak mengatakan hei, bidang angka sangat membosankan memungkinkan menyimpan angka dalam gumpalan dan menggunakan gambar hewan liar untuk mewakili setiap angka, karena itu gila (keren tapi gila). Kami juga tidak memutuskan bahwa kami tidak suka huruf B, dan seperti mimpi buruk Sesame Street yang kejam, gantilah dengan # dalam data kami. Jika B bukan respons yang kami inginkan, kami memberi tahu pengguna "Hei, Anda tidak dapat menempatkan B di sini". Jadi mengapa memperlakukan null secara berbeda?

Jadi hindari nulls yang tidak Anda inginkan pada level aplikasi dan tangani mereka dalam basis data Anda di mana Anda menerimanya jika tidak pasti sebagai jerapah + jerapah = hippo Perselisihan data tidak berguna Anda akan membuat Anda dalam masalah.


sumber
2
Orang tua saya tidak malas dan saya tidak punya nama tengah. Tidak semua orang tinggal di AS.
ypercubeᵀᴹ
1
Itu dimaksudkan sebagai contoh yang ringan hati, tidak ada pelanggaran berarti. Tentu saja ada banyak orang tanpa nama tengah (titik pertama) karena banyak alasan yang cukup valid (titik utama). Null di kolom ini tidak memberi tahu Anda tentang mengapa itu hilang. Tidak yakin dengan sudut pandang geo-politik Anda - Saya tidak tinggal di AS tetapi sebenarnya memiliki nama tengah. Sulit untuk membuat asumsi berdasarkan data yang hilang kurasa.
Jangan tersinggung. Saya benar-benar mengangkat jawaban Anda. Saya pikir Anda memukul paku dengan titik utama Anda bahwa ada perbedaan antara tidak menerima / mengizinkan Nulls dalam database dan mengganti Nulls dengan nilai ajaib.
ypercubeᵀᴹ
5
Saya akan senang jika nama tengah saya adalah "-5000"! : D
Philᵀᴹ