Apakah ada alasan kuat mengapa kolom dalam SQL nullable secara default?

8

Sebagai seorang siswa CS, saya telah belajar banyak bahasa pemrograman selama bertahun-tahun, yang sebagian besar memiliki konsep "nullable" atau "opsional". Perhatikan bahwa saya tidak berbicara tentang pointer atau referensi nol, atau bahasa yang diketik dengan lemah seperti JavaScript di mana pun bisa null. Contoh dari apa yang saya bicarakan meliputi boost::optional(C ++), java.util.Optional(Java 8.0), prelude.Maybe(Haskell), dan semua '?' jenis (mis int?. float?, C # dan Kotlin). Ini adalah konstruksi yang menambahkan nullability ke tipe yang sebelumnya tidak dapat nullable dalam sistem tipe statis yang ketat.

SQL memiliki konsep yang sama: tipe seperti INTEGERdapat dibuat nullable atau non-nullable - tetapi ada twist. Dalam SQL, INTEGERnullable secara default, dan harus ditulis secara eksplisit INTEGER NOT NULLagar tidak dapat nullable.

Ini menurut saya sangat kontra-intuitif dan berpotensi berbahaya karena memungkinkan NULL menjadi perilaku default. Jelas SQL sudah ada begitu lama pada saat ini sehingga (kebanyakan) pengembang SQL telah mengembangkan kesadaran yang sehat akan perangkap NULL. Tetapi saya tidak dapat membayangkan bahwa pada masa-masa awal NULL sering merayap di tempat-tempat yang tak terduga dan bermasalah.

SQL memang mendahului semua contoh yang saya berikan, jadi mungkin ini hanyalah masalah bagi evolusi sejarah. Namun, saya harus bertanya, apakah ada alasan bagus untuk bahasa dirancang seperti ini, dengan jenis yang dapat dibatalkan secara default?

Jika demikian, apakah itu hanya alasan historis, atau apakah logika mendukung desain database saat ini?

Sunting: Saya tidak bertanya mengapa NULL adalah bagian dari SQL atau mengapa kolom nullable berguna. Saya hanya bertanya mengapa kolom dapat dibatalkan secara default . Sebagai contoh, mengapa kita menulis:

column1 FLOAT,
column2 FLOAT NOT NULL

Daripada:

column1 FLOAT NULLABLE,
column2 FLOAT
ApproachingDarknessFish
sumber
2
Belajarlah untuk menerima jawaban ini: "Tidak ada alasan, itu hanya kebijakan kami."
2
Karena kadang-kadang konsep "Saya tidak tahu" harus diwakili dalam database dengan jelas
Newtopian
@Newtopian yang menjelaskan mengapa NULL dalam bahasa ini. Saya bertanya mengapa NULL diizinkan kolom secara default.
ApproachingDarknessFish
5
Karena "Saya tidak tahu" secara mengejutkan umum dalam informasi basis data. Untuk menggambarkan hal ini dengan sebuah contoh. Bayangkan formulir web di mana SETIAP bidang wajib diisi secara default dan betapa menjengkelkannya itu. Dalam database Anda HARUS mengisi SETIAP bidang dengan sesuatu, selalu. Namun dalam representasi domain Anda, sangat mungkin bahwa banyak dari informasi ini tidak penting dan dapat dibiarkan "tidak diketahui" tanpa efek buruk (asalkan Anda menjaga kode Anda dengan benar). Bahkan saya akan bertaruh bahwa dalam sebagian besar aplikasi sebagian besar informasi termasuk dalam kategori tidak penting ini, maka standarnya terlihat
Newtopian
@Newtopian Baiklah. Buat jawaban itu.
ApproachingDarknessFish

Jawaban:

25

Di Uni saya diajari bahwa yang sebaliknya adalah benar. Jauh lebih berbahaya membuat sesuatu not nulltanpa alasan. Dengan bidang nullable, hal terburuk yang bisa terjadi adalah Anda tersandung aplikasi mengakses data. Oh sayang, kembali dan perbaiki aplikasinya ...

Dengan bidang bukan-nol Anda membuatnya tidak mungkin untuk menambahkan catatan karena beberapa bidang arbitrer tidak tersedia. Sekarang Anda perlu mengubah model data dan berpotensi memperbaiki hasilnya di BANYAK tempat yang berbeda ...

Ini baik untuk dianggap nullsebagai "tidak dikenal". Jika ada alasan yang masuk akal mengapa Anda ingin memasukkan catatan tanpa mengetahui sesuatu maka itu harus dibatalkan.

Salah satu dosen universitas saya menggambarkannya seperti ini:

Secara apokrip, saya pernah mendengar tentang sistem penjualan di AS yang mengharuskan nomor jaminan sosial pelanggan untuk melakukan penjualan. Semua operator till lakukan ketika orang asing datang ke kasir adalah masukkan 000-00-0000. Tetapi kemudian orang lain akan memasukkan 123-45-6789. Ini membuat tidak mungkin mengidentifikasi sampah. Jauh lebih baik membiarkan bidang kosong daripada memaksanya memuat sampah.

Atau cerita lain. Saya benar-benar ditolak asuransi mobil karena saya tidak punya dua nomor telepon. Mereka benar-benar tidak akan memberi saya asuransi kecuali saya memberi mereka dua. Orang penjualan menyarankan saya hanya memberikan yang salah. Pada akhirnya saya menolak berbohong kepada perusahaan asuransi dan hanya pergi dengan perusahaan lain.

Dalam praktiknya cadangan not nulluntuk bidang yang diperlukan untuk membuat catatan masuk akal. Sebagai contoh:

Tabel tempat dengan bidang (ID, Nama Tempat, Negara, Bujur, Lintang) ... "bujur" "lintang" harus dibatalkan sehingga Anda dapat menyimpan keberadaan tempat sebelum Anda tahu di mana itu.

Tetapi jika Anda memiliki tabel yang tujuan utamanya adalah untuk menyimpan koodinat geografis dengan bidang (Item_id, bujur, lintang) seluruh catatan tidak ada artinya jika bujur dan lintang adalah nol. Oleh karena itu dalam hal ini mereka tidak boleh null

Dalam pengalaman profesional saya sejak uni, ada lebih banyak bidang yang dapat opsional daripada harus wajib.

Philip Couling
sumber
Siapa yang Anda kutip di blok kutipan di atas?
Robert Harvey
Dosen Universitas.
Philip Couling
8

Menurut saya ini sangat kontra-intuitif ...

Intuitif ada di mata yang melihatnya dan pendapat Anda tentang hal itu dibentuk oleh hal-hal yang telah Anda ketahui. Saya berasal dari waktu ketika keselamatan semacam itu tidak standar dan alat tidak menunjukkan ketika Anda melakukan kesalahan. Saya telah menggunakan gergaji rantai tanpa pelindung pisau cukup lama sehingga insting pertama saya adalah untuk menghindari intuisi sepenuhnya, kembali ke DDL dan mencari tahu apa asumsi skema yang akan saya buat tentang datanya.

... dan berpotensi berbahaya karena membiarkan NULL menjadi perilaku default.

Saya pikir Anda melebih-lebihkan bahaya relatif. NOT NULLmemiliki perangkap sendiri yang dapat menyebabkan bug yang sama-sama berbahaya. (Menghitung mereka akan menjadi makanan untuk pertanyaan yang berbeda.)

Perancang tabel selalu memiliki opsi untuk membatasi kolom NULLatau NOT NULLdan akan melakukan satu atau yang lain untuk menyiasati default, apa pun itu. Tidak membatasi kolom dengan benar adalah kegagalan pengembang untuk mengikuti aturan bisnis. Tidak melakukan hal yang benar di tempat lain berdasarkan definisi kolom adalah kegagalan pengembang untuk memahami data yang diserahkannya. Tidak ada perbaikan teknis untuk keduanya.

Namun, saya harus bertanya, apakah ada alasan bagus untuk bahasa dirancang seperti ini, dengan jenis yang dapat dibatalkan secara default?

Tidak, tidak ada. Karena keduanya memiliki bahaya, tidak ada alasan yang baik untuk bahasa tersebut dirancang sebaliknya. Itu intinya untuk mengambil racun Anda.

Blrfl
sumber
6

Kolom nullable diperlukan dalam SQL karena gabungan luar (juga dikenal sebagai gabungan kiri atau gabungan kanan). Ketika baris di satu sisi gabungan tidak memiliki kecocokan di sisi lain, bidang untuk sisi lain harus memiliki NULL. Karena output dari gabungan dapat memiliki kolom nullable, tabel dasar juga harus mendukungnya karena prinsip penutupan relasional (yang pada dasarnya menyatakan hasil kueri atau tampilan harus tidak dapat dibedakan dari tabel dasar).

Mengingat hal ini, SQL harus mendukung kolom yang dapat dibatalkan. Di sisi lain, kolom non-nullable adalah fitur sekunder - SQL masih bisa berfungsi tanpa mereka.

JacquesB
sumber
4

Mari kita balikkan dan katakan Anda benar. Katakanlah integer Anda bukan nol secara default.

Yang berarti harus memiliki nilai default. Bahkan ketika itu tidak diketahui.

Jadi ketika Anda memperbarui tabel orang Anda dan Anda memiliki dua pilihan: Tidak mungkin untuk memperbarui tabel karena Anda tidak memasukkan bobot. Atau ketika Anda tidak memberikan argumen bobot yang dimasukkan ke dalam standar "-1 kilo" ketika tidak diketahui.

Kedua situasi tidak diinginkan. Anda ingin dapat menambah pelanggan, bahkan jika Anda tidak tahu beratnya. Tetapi juga, Anda tidak ingin memiliki nilai "proxy". Nilai yang merupakan tempat penampung tetapi dapat memiliki makna nyata, misalnya: dapat digunakan dalam fungsi matematika seperti "rata-rata" tetapi bukan nilai nyata.

Maksud saya saat menghitung bobot rata-rata, -1 adalah nilai yang valid dalam fungsi rata-rata matematika Anda, tetapi tidak sebagai bobot orang. Anda menggunakan null dan sekarang fungsi rata-rata Anda tahu untuk mengabaikan nilai itu.

Juga, saya tidak akan benar-benar membandingkan SQL dengan bahasa pemrograman ketika membahas nol, mereka secara inheren berbeda, null dalam SQL sangat banyak bagian dari teori desain database relasional.

Pieter B
sumber
3

Tidak. Tidak ada alasan kuat mengapa SQL default menjadi nullable. Faktanya, banyak peneliti terkemuka dalam teori database relasional tidak setuju dengan keputusan desain ini, mungkin yang paling terkenal adalah Chris Date , seorang kolaborator yang sering dengan perancang asli dari database relasional, Edgar Codd . Date (bersama dengan rekan penulis Hugh Darwen) menerbitkan sebuah buku terkenal tentang teori relasional (" The Third Manifesto ") yang menjelaskan prinsip-prinsip untuk desain alternatif untuk keluarga bahasa relasional yang mereka sebut "D", bersama dengan contoh bahasa yang disebut " Tutorial D ".

Bahasa D dilarang secara eksplisit dari mendukung nilai NULL ("D tidak akan menyertakan konsep" hubungan "di mana beberapa" tuple "menyertakan beberapa" atribut "yang tidak memiliki nilai."). Sebagai gantinya, nilai opsional didukung dengan memiliki tipe data alternatif yang menyertakan penanda tempat "tidak ada" atau nilai serupa. Bahasa D menyediakan model yang kaya untuk jenis yang ditentukan pengguna yang akan memungkinkan jenis asli apa pun diperluas dengan nilai tambahan tersebut.

Ada alasan teoritis yang meyakinkan mengapa ini adalah ide yang bagus, dan Date & Darwen telah menulis banyak tentang ini, serta keputusan lain yang mereka buat dalam desain mereka. Saya sangat merekomendasikan membaca karya mereka tentang topik ini.

Jules
sumber
1
Saya tidak mengikuti / tidak setuju dengan logika Anda. Saya percaya Anda menggabungkan dua masalah terpisah. Masalah a) haruskah suatu bahasa mewakili nol sama sekali? Masalah b) dalam bahasa yang tidak menggunakan null berarti "tidak-ada" haruskah bidang memperbolehkan null (tidak-ada) secara default? Mungkin Anda telah melewatkan langkah dalam jawaban Anda ... Apakah ada item c) Dalam D, atribut tidak boleh mengizinkan tidak-hadir secara default karena .... <masukkan argumen di sini>
Philip Couling
2
Komentar pertama saya sulit untuk diikuti jadi saya akan mengatakannya secara sederhana: Representing x with null is a bad ideaJangan menyimpulkan itu allowing x by default is bad. Ergo tidak menyiratkan bahwaallowing null by default is bad where null is the only available representation of x
Philip Couling
1
@jules apa perbedaan konsep antara bidang int menjadi nullable dan bidang int memiliki tipe data alternatif: 'tidak ada'? Bukankah itu sama dengan nama yang berbeda? Null juga merupakan tipe data alternatif untuk int.
Pieter B
1
@PieterB Ya dan tidak. Masalah mendasar dari nol adalah bahwa kata itu digunakan untuk berarti terlalu banyak hal yang berbeda. Dalam SQL itu bisa berarti "tidak ada" atau itu bisa berarti "tidak diketahui". Argumen D adalah bahwa semua ini harus didefinisikan dengan jelas dan "null" catch-all tidak boleh digunakan. Tidak mempelajarinya secara rinci, saya menduga bahwa pendukung D akan menganjurkan Not Present = Not Presentdi mana dalam SQL tidak ada null = nullatau null != nullbenar.
Philip Couling
Codd mengatakan bahwa harus ada lebih banyak jenis Null, saya pikir dia mengusulkan 4 awalnya dan kemudian diperluas menjadi 17. Programmer berkata: Mengapa kita membuang-buang upaya membedakan cara mengatakan "Saya tidak tahu"? Tentu, ada yang diketahui tidak diketahui, dan tidak diketahui yang tidak diketahui, tetapi sebenarnya, data adalah yang diketahui, dan tidak banyak lagi.
1

Saya tidak setuju dengan premis Anda tentang apa yang seharusnya menjadi default, tetapi praktik yang baik untuk tidak menganggap apa pun sebagai pengembang. Memeriksa spesifikasi pada tabel database seharusnya tidak terlalu sulit.

Lebih dari perspektif DBA di mana Anda akan diminta untuk memuat data massal terutama ketika menggabungkan dari sistem lain, Anda lebih baik mengetahui pengaturan untuk setiap bidang apakah Anda memiliki data untuk dimasukkan ke dalamnya atau tidak.

Bisnis dan aplikasi dijalankan oleh orang-orang. Jika mereka bukan seorang programmer, definisi "tidak pernah" dan "selalu" tidak persis sama dan akan berubah seiring waktu. Pengaturan nol saat ini pada bidang yang diberikan tidak boleh kabur.

JeffO
sumber
Benar, beban massal, migrasi dan sebagainya akhirnya mengalahkan semua masalah lain, karena data adalah apa yang nyata dan bernilai, dan program hanyalah alat sementara yang membentuknya. Adakah yang melihat kartu menekan atau mesin rekaman dari sensus 1900? Tidak, tetapi datanya masih tersedia. Berapa kali dipindahkan dari satu sistem ke sistem lainnya, bahkan dalam setahun terakhir? Setiap kali seseorang menggunakannya, saya kira.
0

Database adalah binatang yang berbeda dari bahasa pemrograman normal.

Karena skema tabel diatur, semua data harus ada saat menyimpan informasi ke baris. Namun banyak dari data ini mungkin tidak diperlukan untuk membuat representasi yang valid dari objek model yang pernah dimuat dalam kode Anda. Dengan mensyaratkan bahwa semua data harus non-nol dan diisi akan berarti bahwa bidang-bidang yang tidak wajib ini harus mengandung nilai, namun mereka belum memilikinya, mereka "tidak dikenal".

Bayangkan harus mengisi SEMUA bidang di formulir web SEMUA waktu karena mereka tidak boleh nol dalam database mereka harus menerima nilai ... resep untuk kegilaan itu!

Anda dapat mengatur beberapa nilai yang dicadangkan untuk mewakili tidak adanya data, string kosong, angka tertentu, tanggal tertentu dll tergantung pada tipe data tetapi nilai apa yang harus dipilih? Maka Anda perlu memastikan bahwa semua orang setuju bahwa nilai-nilai sewenang-wenang ini sebenarnya berarti "tidak dikenal" dan bukan "1 Januari 1970" misalnya. Keengganan kosong dapat mengambil banyak bentuk dan membawa Anda pada jalan memutar berbelit-belit hanya karena seseorang mengatakan nol itu buruk. Seberapa kompleks Anda siap untuk mendapatkan hanya untuk menghindari berurusan dengan nol?

Memiliki nilai universal tunggal untuk segala sesuatu yang tidak diketahui saya temukan jauh lebih disukai daripada menggunakan beberapa set nilai konstan arbitrer. Saya tidak mengatakan nilai konstan buruk dan null lebih baik, jika model Anda dilayani dengan baik oleh konstanta untuk mewakili informasi ini maka dengan segala cara gunakan itu tetapi ada banyak situasi di mana nol adalah yang paling cocok. Untuk semua pembenci nol, ini adalah situasi jika nol ditolak maka harus diciptakan!

Melihat betapa meresapnya konsep "tidak dikenal" dalam database maka ya, saya akan mengatakan bahwa membuat nilai-nilai nullable sebagai default sangat masuk akal.

Pergi lebih dalam dan melihat jawaban lain di sini saya tidak akan terkejut mengetahui bahwa nol bukan hanya "fitur bahasa" tetapi bagian integral dari teori yang mendasari di mana SQL didasarkan. Seseorang dapat menghilangkan C (kecepatan cahaya) dari relativitas, tetapi konsep kecepatan maksimum absolut tetap dan harus tetap diekspresikan sehingga akan kembali dalam beberapa bentuk atau bentuk.

Newtopian
sumber
0

Jawaban singkat: kompatibilitas ke belakang.

Jawaban panjang:

Dalam database yang sepenuhnya dinormalisasi, NULL tidak diperbolehkan di kolom apa pun. Sebagai contoh, misalkan ada tabel yang disebut MailingAddress yang memiliki kolom PostOfficeBox, yang merupakan bilangan bulat. Karena tidak semua orang memiliki kotak pos, ada dua cara untuk mengimplementasikannya.

Pertama, NULL dapat diizinkan di kolom.

Kedua, PostOfficeBox dihapus dari MailingAddress dan tabel baru, PostOfficeBox dibuat dengan Nomor kolom dan PK-nya menjadi FK ke MailingAddress. Tapi sekarang dua pertanyaan diperlukan untuk mendapatkan alamat surat: satu untuk yang tanpa kotak pos dan satu lagi untuk yang punya.

SQL memungkinkan NULL dalam kolom untuk tujuan praktis.

shawnhcorey
sumber