Penjelasan Nilai SQL NULL: IS NULL, COALESCE, NULLIF dan Jebakan yang Harus Dihindari
NULL menyebabkan beberapa bug paling tenang di SQL, dengan kueri yang berjalan tanpa kesalahan namun kehilangan baris atau rata-rata yang miring. Pelajari bagaimana NULL sebenarnya berperilaku, dengan contoh yang telah diuji, dan cara menanganinya dengan aman.
- NULL berarti nilai yang hilang atau tidak diketahui. Ini bukan nol, dan ini bukan string kosong.
- Uji dengan
IS NULL, karena= NULLtidak pernah cocok dengan apa pun. - Kebanyakan perhitungan dengan NULL menghasilkan NULL, dan
WHEREhanya menyimpan baris yang benar saja. - Agregat melewati NULL, yang secara diam-diam dapat mengubah rata-rata.
Kueri berjalan tanpa kesalahan dan mengembalikan angka yang tampak masuk akal, namun barisnya hilang dan rata-ratanya salah. Nilai SQL NULL sangat sering menjadi penyebabnya. NULL tidak berperilaku seperti nilai normal lainnya, dan hal ini menarik perhatian para pengembang pemula dan berpengalaman.
Panduan ini menunjukkan dengan tepat bagaimana perilaku NULL. Kami menjalankan setiap kueri di SQLite 3.50, dan hasil yang ditampilkan berasal dari proses tersebut. Sebagian besar perilaku ini adalah SQL standar, dan kami mencatat perbedaan database, seperti urutan NULL, dan perlakuan Oracle terhadap string kosong.
Apa itu NULL?
NULL adalah penanda yang berarti suatu nilai hilang atau tidak diketahui. Ini bukan nilai dalam pengertian biasa, jadi ini semua adalah hal yang berbeda:
| Nilai | Artinya | Contoh untuk kolom telepon |
|---|---|---|
BATAL |
Tidak diketahui atau tidak disediakan | Kami tidak tahu nomornya |
'' |
Nilai teks kosong yang diketahui | Dikirim sebagai kosong |
0 |
Angka nol | Tidak relevan dengan teks, tetapi nyata untuk jumlah |
Perbedaannya penting terutama untuk jumlah. Bonus 0 berarti orang tersebut tidak menerima apa pun. Bonus NULL berarti belum ada yang tahu.
Tabel sampel
CREATE TABLE employees (
id INT, name TEXT, phone TEXT, bonus INT, manager_id INT
);
INSERT INTO employees VALUES
(1,'Meera','555-0101',500,NULL),
(2,'Arjun',NULL,300,1),
(3,'Sara','',NULL,1),
(4,'Ravi',NULL,NULL,2);
Perhatikan bahwa Sara memiliki string kosong untuk telepon, sedangkan Arjun dan Ravi memiliki NULL. Keduanya diperlakukan sangat berbeda.
Menguji NULL
Inilah kesalahan yang dilakukan hampir semua orang pada awalnya:
SELECT name FROM employees WHERE phone = NULL;
-- (no rows)
SELECT name FROM employees WHERE phone IS NULL;
-- Arjun
-- Ravi
SELECT name FROM employees WHERE phone IS NOT NULL;
-- Meera
-- Sara
Kueri pertama adalah SQL yang valid dan tidak memberikan kesalahan. Itu tidak menghasilkan apa pun, karena membandingkan apa pun dengan NULL tidak pernah benar. Sara muncul di bawah IS NOT NULL, karena string kosong adalah nilai nyata. Namun, di Oracle, string kosong diperlakukan sebagai NULL, yang merupakan pengecualian.
Logika tiga nilai
Di sebagian besar bahasa pemrograman, suatu kondisi bernilai benar atau salah. SQL menambahkan hasil ketiga: tidak diketahui. Jika Anda tidak mengetahui suatu nilai, Anda tidak dapat mengatakan apakah nilainya sama dengan 5. Dan dua nilai yang tidak diketahui tidak diketahui sama, itulah sebabnya NULL = NULL tidak benar. Dalam pengujian kami, semua ini menghasilkan NULL:
SELECT NULL = NULL, NULL <> 1, 1 + NULL, 'a' || NULL;
-- NULL | NULL | NULL | NULL
Menggabungkan kondisi mengikuti aturan yang cermat. Berikut adalah hasil dari proses kita, dimana 1 adalah benar dan 0 adalah salah:
| Ekspresi | Hasil | Mengapa |
|---|---|---|
BENAR DAN BATAL |
BATAL | Tergantung pada bagian yang tidak diketahui |
SALAH DAN BATAL |
Salah | Salah apa pun yang tidak diketahui |
BENAR ATAU BATAL |
Benar | Benar apa pun yang tidak diketahui |
SALAH ATAU BATAL |
BATAL | Tergantung pada bagian yang tidak diketahui |
BUKAN BATAL |
BATAL | Lawan kata dari tidak diketahui adalah tidak diketahui |
Baris yang hilang dari WHERE
WHERE menyimpan baris hanya jika kondisinya benar. Baris yang hasilnya tidak diketahui akan dihilangkan, begitu juga dengan baris yang salah. Hal ini membawa hasil yang mengejutkan:
SELECT name FROM employees WHERE phone <> '555-0101';
-- Sara
Anda mungkin mengharapkan Arjun dan Ravi muncul, karena telepon mereka jelas bukan nomor tersebut. Namun ponsel mereka tidak diketahui, sehingga hasilnya tidak diketahui, dan mereka menghilang. Untuk menyertakannya, ucapkan secara eksplisit: WHERE phone <> '555-0101' OR phone IS NULL. Negasi juga tidak membantu:
SELECT name FROM employees WHERE NOT (bonus > 400);
-- Arjun
Sara dan Ravi tidak memiliki bonus, jadi mereka tidak muncul di bonus > 400 maupun kebalikannya. Hal penting yang perlu diingat: suatu kondisi dan negasinya tidak selalu mencakup setiap baris.
COALESCE: menyediakan cadangan
COALESCE mengembalikan nilai non-NULL pertama dalam daftarnya, dan berfungsi di semua database utama:
SELECT COALESCE(NULL, NULL, 'third', 'fourth');
-- third
SELECT name, COALESCE(phone, 'no phone') FROM employees;
-- Meera | 555-0101
-- Arjun | no phone
-- Sara |
-- Ravi | no phone
Sara masih tampak kosong, karena string kosong bukan NULL. Ada fungsi serupa, seperti IFNULL di MySQL dan SQLite, ISNULL di SQL Server dan NVL di Oracle. COALESCE adalah pilihan portabel. Poin kami sebelumnya tentang penghitungan juga berlaku di sini. bonus + 100 memberikan NULL untuk siapa pun tanpa bonus, jadi tulis COALESCE(bonus, 0) + 100 jika memperlakukan bonus yang hilang sebagai nol sudah benar untuk bisnis Anda.
NULLIF: mengubah nilai menjadi NULL
NULLIF(a, b) mengembalikan NULL jika kedua nilainya sama, dan sebaliknya mengembalikan a. Dua kegunaan sangat membantu. Itu dapat membersihkan nilai placeholder:
SELECT name, NULLIF(phone, '') FROM employees WHERE id = 3;
-- Sara | NULL
SELECT name FROM employees
WHERE COALESCE(NULLIF(phone, ''), '') = '';
-- Arjun
-- Sara
-- Ravi
Kueri kedua adalah cara praktis untuk menemukan nilai yang “hilang atau kosong”. Hal ini juga dapat mencegah pembagian dengan nol, yang menimbulkan kesalahan di banyak database:
SELECT total / NULLIF(quantity, 0) FROM sales;
Ketika quantity adalah 0, ini memberikan NULL daripada gagal. Dalam pengujian kami, SELECT 100 / NULLIF(0, 0) mengembalikan NULL.
Agregat lewati NULL
Di sinilah NULL melakukan kerusakan paling besar pada laporan:
SELECT COUNT(*), COUNT(bonus), SUM(bonus), AVG(bonus),
AVG(COALESCE(bonus, 0))
FROM employees;
-- 4 | 2 | 800 | 400.0 | 200.0
| Ekspresi | Hasil | Apa artinya |
|---|---|---|
COUNT(*) |
4 | Semua baris |
COUNT(bonus) |
2 | Hanya baris dengan bonus |
SUM(bonus) |
800 | NULL diabaikan |
AVG(bonus) |
400 | 800 dibagi 2, bukan 4 |
AVG(BERGABUNG(bonus, 0)) |
200 | 800 dibagi 4 |
Jadi berapa rata-rata bonusnya, 400 atau 200? Itu tergantung pada apa arti NULL dalam data Anda. Jika NULL berarti “tidak ada bonus yang dibayarkan”, maka 200 benar. Jika artinya “belum diputuskan”, maka 400 mungkin benar. Basis data tidak dapat membuat keputusan ini untuk Anda, jadi pertanyaannya harus ditujukan kepada seseorang yang mengetahui bisnis tersebut.
Jebakan terkait: SUM yang tidak memiliki nilai adalah NULL, bukan 0. Ketika kita hanya menjumlahkan baris tanpa bonus, kita mendapatkan NULL, sementara COUNT menghasilkan 0. Kode aplikasi yang mengharapkan suatu angka dapat mogok dalam hal ini, jadi bungkuslah: COALESCE(SUM(bonus), 0).
Tips: Jika total laporan terlihat tidak ada, bandingkan COUNT(*) dengan COUNT(column). Setiap celah di antara keduanya langsung memberi tahu Anda berapa banyak NULL yang dimiliki kolom tersebut.
KELOMPOK BERDASARKAN, sortir dan BERBEDA
Meskipun NULL “tidak sama” dalam perbandingan, operasi ini memperlakukannya sebagai satu kelompok:
SELECT bonus, COUNT(*) FROM employees GROUP BY bonus ORDER BY bonus;
-- NULL | 2
-- 300 | 1
-- 500 | 1
SELECT DISTINCT bonus FROM employees;
-- 500, 300, NULL
Lihat SQL GROUP BY dan HAVING untuk mengetahui lebih lanjut tentang pengelompokan. Urutan pengurutan adalah tempat dimana database benar-benar berbeda. SQLite dan MySQL memperlakukan NULL sebagai nilai terkecil, sedangkan PostgreSQL dan Oracle memperlakukannya sebagai nilai terbesar. Jadi ORDER BY bonus DESC yang sama dapat menempatkan NULL sebagai yang terakhir di satu dan yang pertama di yang lain. PostgreSQL, Oracle, dan SQLite modern memungkinkan Anda menyatakan hal ini secara langsung, menggunakan NULLS FIRST atau NULLS LAST.
Bergabung
Kondisi gabungan yang menggunakan = tidak pernah cocok dengan NULL, jadi baris dengan kunci NULL dikeluarkan dari gabungan dalam:
SELECT e.name FROM employees e
JOIN employees m ON m.id = e.manager_id;
-- Arjun, Sara, Ravi (Meera is gone)
SELECT e.name, m.name FROM employees e
LEFT JOIN employees m ON m.id = e.manager_id;
-- Meera | NULL
-- Arjun | Meera
-- Sara | Meera
-- Ravi | Arjun
Meera tidak memiliki manajer, jadi gabungan dalam secara diam-diam menghapus baris itu. A LEFT JOIN menyimpannya, dan itu juga membuat NULL sendiri untuk sisi yang hilang. Baca selengkapnya di penjelasan gabungan SQL.
Perangkap TIDAK DALAM
Satu NULL dalam daftar NOT IN menghapus setiap hasil:
SELECT name FROM employees WHERE manager_id NOT IN (1);
-- Ravi
SELECT name FROM employees WHERE manager_id NOT IN (1, NULL);
-- (no rows)
Bentuk kedua berarti manager_id <> 1 AND manager_id <> NULL, dan bagian terakhir itu tidak akan pernah benar. Hal ini sangat berbahaya pada subquery, dimana NULL dapat muncul tanpa disadari. Gunakan NOT EXISTS sebagai gantinya, seperti yang dijelaskan dalam tutorial subkueri SQL kami. Meera juga hilang dari hasil pertama, karena baris manager_id itu adalah NULL.
Mendesain dengan NULL
- Gunakan
NOT NULLsecara default. Izinkan NULL hanya jika suatu nilai benar-benar hilang. - Tambahkan default yang masuk akal. Misalnya,
quantity INT NOT NULL DEFAULT 0. - Jangan gunakan nilai ajaib. Tanggal 01-01-1900 atau usia -1 yang mewakili “tidak diketahui” akan merusak perhitungan Anda.
- Ketahui perilaku UNIK. Kebanyakan database mengizinkan beberapa NULL dalam kolom
UNIQUE, dan pengujian kami menyisipkan dua tanpa kesalahan. SQL Server adalah pengecualian, karena biasanya mengizinkannya. - Ingat bahwa kunci utama tidak boleh NULL. Lihat kunci utama vs kunci asing.
- Uji dengan NULL. Data pengujian tanpa NULL menyembunyikan bug ini. Sertakan mereka dengan sengaja, seperti yang Anda lakukan pada kasus tepi lainnya.
Penutup
Perlakukan NULL sebagai “tidak diketahui”, dan sebagian besar perilakunya mulai masuk akal: tidak diketahui ditambah satu tidak diketahui, dan tidak diketahui sama dengan tidak diketahui tidak diketahui kebenarannya. Audit salah satu laporan Anda minggu ini. Periksa kolom yang dapat dibatalkan menggunakan COUNT(*) terhadap COUNT(column), cari NOT IN, dan putuskan apa arti NULL di setiap rata-rata.
Pertanyaan yang sering diajukan
Apa itu NULL dalam SQL?
NULL adalah penanda nilai yang hilang atau tidak diketahui. Ini berbeda dari nol dan dari string kosong, dan memerlukan penanganan khusus dalam perbandingannya.
Mengapa = NULL tidak berfungsi?
Membandingkan apa pun dengan NULL memberikan hasil yang tidak diketahui, bukan benar, jadi WHERE membuang baris tersebut. Gunakan IS NULL atau IS NOT NULL untuk mengujinya.
Apa perbedaan antara COALESCE dan ISNULL?
COALESCE adalah SQL standar dan menerima banyak argumen. ISNULL khusus untuk SQL Server dan membutuhkan dua. Untuk kode portabel, pilih COALESCE.
Apakah COUNT menyertakan nilai NULL?
COUNT(*) menghitung semua baris, termasuk baris dengan NULL. COUNT(column) hanya menghitung baris yang kolomnya bukan NULL, yang dapat menghasilkan angka lebih kecil.
Apakah NULL sama dengan string kosong?
Tidak, di sebagian besar database. String kosong adalah nilai yang diketahui tanpa karakter, dan NULL berarti tidak diketahui. Oracle adalah pengecualian, karena memperlakukan string kosong sebagai NULL.
Teruslah belajar
Butuh bantuan dengan pengujian, WordPress atau SEO?
Kami membantu tim mengirimkan perangkat lunak yang lebih baik dan mengembangkan situs mereka. Beritahu kami apa yang sedang Anda kerjakan dan kami akan menyarankan langkah selanjutnya yang jelas.
Panduan lebih lanjut tentang pengujian, AI & pengembangan modern
Menikmati artikel ini? Pilih topik dan langsung masuk ke tutorial terbaru kami.
Penjelasan Halusinasi AI: Mengapa Model Bahasa Memperbaiki Masalah dan Cara Menguranginya
Halusinasi AI menjelaskan: apa itu, mengapa model bahasa memproduksinya, tipe umum, cara menguranginya dengan landasan dan petunjuk, dan pemeriksaan…
Baca artikel →DevOpsPenjelasan Variabel Lingkungan: File .env, Rahasia, dan Konfigurasi Dilakukan dengan Benar
Variabel lingkungan dijelaskan dengan contoh Python yang kami jalankan: membaca dan mengaturnya, mengapa setiap nilai berupa string, file .env, pewa…
Baca artikel →Pengembangan perangkat lunakPenjelasan Pembatasan Kecepatan API: Algoritma, Header, dan Penanganan 429 Kesalahan
Pembatasan laju API dijelaskan dengan simulasi yang kami jalankan: keranjang token, jendela tetap, jendela geser, respons 429, header batas laju, pe…
Baca artikel →Otomatisasi pengujianMengejek dengan Python: unittest.mock, patch dan Kesalahan yang Membuat Tes Berbohong
Mengejek dengan Python dengan unittest.mock, menguji: Mock dan return_value, side_effect, menambal di mana nama digunakan, spesifikasi dan autospec,…
Baca artikel →Pengujian perangkat lunakPenjelasan Cakupan Kode: Cakupan Jalur vs Cabang dan Apa Arti 100% Sebenarnya
Cakupan kode dijelaskan dengan coverage.py yang sebenarnya dijalankan: cakupan garis, cabang dan kondisi, membaca laporan, mengapa cakupan 100% masi…
Baca artikel →Basis data & SQLDELETE vs TRUNCATE vs DROP dalam SQL: Perbedaan, Rollback dan Kapan Menggunakan Masing-Masing
DELETE vs TRUNCATE vs DROP dijelaskan dengan SQL yang diuji: apa yang dihapus, rollback, pemicu, reset identitas, kecepatan, dan perbedaan PostgreSQ…
Baca artikel →Basis data & SQLPenjelasan Tampilan SQL: Membuat, Menggunakan, dan Menghindari Kesalahan, Dengan Contoh
Tampilan SQL dijelaskan dengan kueri yang kami jalankan: membuat tampilan, hasil langsung, menyembunyikan kolom, kinerja, tampilan yang dapat diperb…
Baca artikel →Pengembangan perangkat lunakAntarmuka TypeScript vs Tipe: Perbedaan Nyata, Diuji Dengan Kompiler
Antarmuka TypeScript vs tipe, diperiksa dengan kompiler sebenarnya: apa yang bisa dilakukan keduanya, apa yang hanya bisa dilakukan satu orang, peng…
Baca artikel →Pengembangan perangkat lunakPenjelasan Python *args dan **kwargs: Fungsi Fleksibel Dengan Contoh Jelas
Python *args dan **kwargs dijelaskan dengan kode yang kami jalankan: pengepakan dan pembongkaran, urutan parameter, argumen hanya kata kunci dan pos…
Baca artikel →Pengembangan perangkat lunakFungsi Python Lambda: Sintaks, Kegunaan Sebenarnya, dan Kapan Tidak Digunakan
Fungsi python lambda dijelaskan dengan kode yang kami jalankan: sintaksis, pengurutan dengan kunci, peta dan filter, penutupan, jebakan pengikatan a…
Baca artikel →Kecerdasan buatanApa Itu Agen AI? Cara Kerjanya, Dengan Agent Loop Sederhana yang Dapat Anda Jalankan
Apa itu agen AI? Panduan sederhana tentang loop agen, alat, memori, dan pagar pembatas, dengan loop Python kecil yang kami jalankan, risiko nyata da…
Baca artikel →DevOpsPemantauan vs Observabilitas: Perbedaan Nyata, Dengan Log, Metrik, dan Jejak
Penjelasan pemantauan vs observabilitas: kegagalan yang diketahui dan tidak diketahui, log, metrik dan jejak, penelusuran insiden checkout, sinyal e…
Baca artikel →DevOpsVolume Docker vs Bind Mounts: Pertahankan Data Kontainer dengan Cara yang Benar
Volume Docker vs pengikatan pengikat dijelaskan: mengapa data kontainer menghilang, volume yang diberi nama, pengikatan pengikatan, tmpfs, contoh Tu…
Baca artikel →Otomatisasi pengujianTDD vs BDD: Perbedaan Utama, Satu Fitur Dibangun dengan Dua Cara dan Kapan Menggunakan Masing-masing
TDD vs BDD dijelaskan dengan satu fitur diskon yang dibuat dengan dua cara: refactor merah-hijau dengan kode yang kami jalankan, skenario Mengingat-…
Baca artikel →Pengujian perangkat lunakUser Acceptance Testing (UAT): Proses, Checklist dan Contoh Nyata
Pengujian penerimaan pengguna menjelaskan: siapa yang menjalankannya, perbedaannya dengan QA, proses tujuh langkah, templat kasus uji UAT, daftar pe…
Baca artikel →Basis data & SQLPenjelasan Nilai NULL SQL: IS NULL, COALESCE, NULLIF dan Jebakan yang Harus Dihindari
Nilai SQL NULL dijelaskan dengan kueri yang kami jalankan: logika tiga nilai, IS NULL, COALESCE, NULLIF, cara agregat, penggabungan, dan pengurutan …
Baca artikel →Basis data & SQLPernyataan SQL CASE WHEN: Sintaks, Contoh Nyata dan Kesalahan Umum
SQL CASE KETIKA dijelaskan dengan kueri yang kami jalankan: formulir sederhana dan dicari, urutan kondisi, pivot dengan SUM, trik COUNT, pengurutan …
Baca artikel →Pengembangan perangkat lunakApa itu JWT? Token Web JSON Dijelaskan Dengan Contoh Kerja
Apa itu JWT? JSON Web Tokens menjelaskan: tiga bagian, token yang dibuat dan dirusak dalam kode yang kami jalankan, sesi JWT vs, penyimpanan, token …
Baca artikel →Pengembangan perangkat lunakPenjelasan Loop Acara JavaScript: Call Stack, Microtasks, dan Timer Dengan Contoh
Perulangan peristiwa JavaScript dijelaskan dengan kode yang kami jalankan: tumpukan panggilan, antrian tugas dan tugas mikro, mengapa setTimeout 0 t…
Baca artikel →Pengembangan perangkat lunakGenerator Python dan Penjelasan Hasil: Menghemat Memori Dengan Contoh Nyata
Generator dan hasil Python dijelaskan dengan kode yang kami jalankan: bagaimana mereka menjeda dan melanjutkan, mengukur penghematan memori, saluran…
Baca artikel →Kecerdasan buatanApa itu Embedding? Kesamaan Vektor dan Kosinus Dijelaskan Secara Sederhana
Apa itu embeddings? Panduan bahasa sederhana tentang vektor, kesamaan kosinus, dan penelusuran semantik, dengan contoh kecil yang kami jalankan, pen…
Baca artikel →DevOpsPenerapan Biru-Hijau vs Canary: Perbedaan, Kompromi, dan Cara Memilih
Penjelasan penerapan blue-green vs canary: cara kerja masing-masing, biaya, risiko dan rollback, pengelompokan pengguna stabil yang kami uji, migras…
Baca artikel →Pengembangan perangkat lunakGit merge vs rebase: perbedaan, contoh, dan kapan memakai masing-masing
Git merge vs rebase dijelaskan dengan keluaran log nyata, tabel perbandingan, aturan emas rebase, dan alur kerja tim yang aman.
Baca artikel →Pengembangan perangkat lunakList Comprehension Python: Sintaks, Contoh, dan Kapan Harus Dihindari
List comprehension Python dijelaskan: sintaks, filter, if-else, perulangan bersarang, waktu yang diukur, dan kapan perulangan for biasa lebih baik.
Baca artikel →Basis data & SQLPenjelasan SQL JOIN dengan Contoh (Inner, Left, Right, Full)
Pahami SQL JOIN langkah demi langkah dengan tabel dan query contoh: INNER, LEFT, RIGHT, FULL, CROSS, dan SELF, plus kesalahan umum dan tips performa.
Baca artikel →