Di SQL server jika Anda memiliki nullParam=NULL
klausa where, ia selalu bernilai false. Ini berlawanan dengan intuisi dan telah menyebabkan saya banyak kesalahan. Saya mengerti IS NULL
dan IS NOT NULL
kata kunci adalah cara yang tepat untuk melakukannya. Tetapi mengapa SQL server berperilaku seperti ini?
sql
sql-server
null
Byron Whitlock
sumber
sumber
Jawaban:
Anggap null sebagai "tidak dikenal" dalam kasus itu (atau "tidak ada"). Dalam kedua kasus tersebut, Anda tidak dapat mengatakan bahwa keduanya sama, karena Anda tidak tahu nilai keduanya. Jadi, null = null dievaluasi menjadi tidak benar (false atau null, tergantung pada sistem Anda), karena Anda tidak tahu nilai untuk mengatakan bahwa mereka sama. Perilaku ini didefinisikan dalam standar ANSI SQL-92.
EDIT: Ini tergantung pada pengaturan ansi_nulls Anda . jika Anda menonaktifkan ANSI_NULLS, ini AKAN mengevaluasi benar. Jalankan kode berikut sebagai contoh ...
sumber
(NaN == NaN) == false && (NaN != Nan) == false && (NaN < NaN) == false && ...
- karena, yah, jika itu bukan angka, Anda tidak bisa mengatakan banyak tentang itu; itu sesuatu yang tidak diketahui. Konsepnya bagus, bahkan jika tidak intuitif untuk orang-orang yang belum pernah melihatnya.NULL
ekspresi SQL dapat diperlakukan sebagai variabel matematika yang berbeda . Jadi ekspresiNULL = NULL
harus diperlakukan sebagaix = y
, di manax
dany
merupakan variabel tidak terikat. Sekarang jika seseorang bertanya kepada Anda, apa nilainyax = y
? Satu-satunya jawaban yang masuk akal adalah, "beberapaz
". Jadi kami telah(x = y) = z
- atau, menyalinnya kembali ke SQL(NULL = NULL) = NULL
,.Berapa umur Frank? Saya tidak tahu (nol).
Berapa umur Shirley? Saya tidak tahu (nol).
Apakah usia Frank dan Shirley sama?
Jawaban yang benar adalah "Saya tidak tahu" (nol), bukan "tidak", karena Frank dan Shirley mungkin seumuran, kita tidak tahu.
sumber
null = null
hasilFALSE
, bukanNULL
.Di sini saya mudah-mudahan akan memperjelas posisi saya.
Yang
NULL = NULL
mengevaluasi untukFALSE
salah. Peretas dan Tuan menjawab dengan benarNULL
. Inilah sebabnya. Dewayne Christensen menulis kepada saya, dalam komentar untuk Scott Ivey :Mereka bisa berbeda atau mereka bisa sama, Anda tidak tahu sampai seseorang membuka kedua hadiah. Siapa tahu? Anda mengundang dua orang yang tidak mengenal satu sama lain dan keduanya telah melakukan untuk Anda hadiah yang sama - langka, tetapi bukan tidak mungkin § .
Jadi pertanyaannya: apakah kedua UNKNOWN ini menyajikan yang sama (sama, =)? Jawaban yang benar adalah: TIDAK DIKETAHUI (yaitu
NULL
).Contoh ini dimaksudkan untuk menunjukkan bahwa ".. (
false
ataunull
, tergantung pada sistem Anda) .." adalah jawaban yang benar - bukan, hanyaNULL
benar dalam 3VL (atau apakah Anda dapat menerima sistem yang memberikan jawaban yang salah? )Jawaban yang benar untuk pertanyaan ini harus menekankan dua poin ini:
Jadi saya ulangi: SQL tidak ada gunanya memaksa orang untuk menafsirkan properti refleksif kesetaraan, yang menyatakan bahwa:
.. dalam 3VL (
TRUE
,FALSE
,NULL
). Harapan orang akan sesuai dengan 2VL (TRUE
,,FALSE
yang bahkan dalam SQL berlaku untuk semua nilai lainnya), yaitux = x
selalu dievaluasi untukTRUE
, untuk setiap kemungkinan nilai x - tanpa pengecualian.Perhatikan juga bahwa NULL adalah " non-nilai " yang valid (seperti yang dikatakan oleh pembela mereka) yang dapat ditetapkan sebagai nilai atribut (??) sebagai bagian dari variabel relasi. Jadi mereka adalah nilai yang dapat diterima dari setiap jenis (domain), tidak hanya dari jenis ekspresi logis.
Dan ini adalah poin saya :
NULL
, sebagai nilai, adalah "binatang aneh". Tanpa eufemisme, saya lebih suka mengatakan: omong kosong .Saya pikir formulasi ini jauh lebih jelas dan kurang bisa diperdebatkan - maaf atas kemampuan bahasa Inggris saya yang buruk.
Ini hanya salah satu masalah dari NULLs. Lebih baik hindari mereka sepenuhnya, jika memungkinkan.
§ kami prihatin dengan nilai - nilai di sini, sehingga fakta bahwa kedua hadiah selalu dua objek fisik yang berbeda bukanlah keberatan yang valid; jika Anda tidak yakin saya minta maaf, bukankah ini tempat untuk menjelaskan perbedaan antara semantik nilai dan "objek" (Aljabar Relasional memiliki semantik nilai sejak awal - lihat prinsip informasi Codd; Saya pikir beberapa pelaksana DBMS SQL tidak bahkan tidak peduli dengan semantik umum).
§§ pengetahuan saya, ini adalah sebuah aksioma yang diterima (dalam bentuk atau lain, tapi selalu ditafsirkan dalam 2VL a) sejak jaman dahulu dan itu persis karena sangat intuitif. 3VLs (adalah keluarga logika pada kenyataannya) adalah perkembangan yang jauh lebih baru (tapi saya tidak yakin kapan pertama kali dikembangkan).
Catatan: jika seseorang akan memperkenalkan Jenis Bawah , Unit dan Opsi sebagai upaya untuk membenarkan SQL NULLs, saya akan diyakinkan hanya setelah pemeriksaan yang cukup rinci yang akan menunjukkan bagaimana implementasi SQL dengan NULLs memiliki sistem jenis suara dan akan menjelaskan, akhirnya, apa NULLs (ini "nilai-bukan-cukup-nilai") sebenarnya.
Pada bagian selanjutnya saya akan mengutip beberapa penulis. Kesalahan atau kelalaian mungkin milik saya dan bukan dari penulis aslinya.
Joe Celko pada SQL NULLs
Saya melihat Joe Celko sering dikutip di forum ini. Rupanya dia adalah penulis yang sangat dihormati di sini. Jadi, saya berkata pada diri sendiri: "apa yang dia tulis tentang SQL NULL? Bagaimana dia menjelaskan banyak masalah NULL?". Salah satu teman saya memiliki versi ebook SQL Joe Joe untuk kecerdasan: pemrograman SQL tingkat lanjut, edisi ke-3 . Ayo lihat.
Pertama, daftar isi. Hal yang paling mengejutkan saya adalah berapa kali NULL disebutkan dan dalam konteks yang paling beragam:
dan seterusnya. Itu berdering "kasus khusus yang jahat" kepada saya.
Saya akan membahas beberapa kasus ini dengan kutipan dari buku ini, mencoba membatasi diri pada hal-hal yang hakiki, karena alasan hak cipta. Saya pikir kutipan ini termasuk dalam doktrin "penggunaan yang adil" dan mereka bahkan dapat merangsang untuk membeli buku - jadi saya harap tidak ada yang mengeluh (kalau tidak saya perlu menghapus sebagian besar, jika tidak semua). Selain itu, saya akan menahan diri untuk tidak melaporkan cuplikan kode karena alasan yang sama. Maaf soal itu. Beli buku untuk membaca tentang penalaran datail.
Nomor halaman antara tanda kurung dalam apa yang mengikuti.
Lagi-lagi ini "nilai tetapi tidak cukup nilai" omong kosong. Sisanya tampaknya cukup masuk akal bagi saya.
Sepenuhnya dari SQL, NULLs dan infinite:
Implementasi SQL ragu-ragu tentang apa arti sebenarnya NULL dalam konteks tertentu:
Joe Celko mengutip David McGoveran dan CJ Date:
NULL sebagai kecanduan narkoba :
Keberatan unik saya di sini adalah untuk "menggunakannya dengan benar", yang berinteraksi buruk dengan perilaku implementasi tertentu.
(pemisah)
Tetapi UNKNOWN adalah sumber masalah itu sendiri, sehingga CJ Date, dalam bukunya yang dikutip di bawah ini, merekomendasikan dalam bab 4.5. Menghindari Nulls di SQL :
Baca "ASIDE" di UNKNOWN, juga terhubung di bawah ini.
(pemisah)
Keberatan: NULLs membingungkan bahkan orang yang mengenal SQL dengan baik, lihat di bawah.
(pemisah)
(pemisah)
(pemisah)
(pemisah)
(pemisah)
(pemisah)
Membahas GROUP BY:
Ini berarti bahwa untuk GROUP BY klausa NULL = NULL tidak mengevaluasi ke NULL, seperti pada 3VL, tetapi mengevaluasi ke BENAR.
Standar SQL membingungkan:
Dan seterusnya. Saya pikir sudah cukup oleh Celko.
Tanggal CJ pada SQL NULLs
Tanggal CJ lebih radikal tentang NULLs: hindari NULLs di SQL, titik. Faktanya, bab 4 dari SQL dan Teori Relasionalnya: Cara Menulis Akurat Kode SQL berjudul "TANPA DUPLIKAT, TANPA NULL", dengan sub bab "4.4 Apa yang Salah dengan Nulls?" dan "4.5 Menghindari Nulls dalam SQL" (ikuti tautan: terima kasih kepada Google Books, Anda dapat membaca beberapa halaman secara online).
Fabian Pascal pada SQL NULLs
Dari Masalah Praktis dalam Manajemen Basis Data - Referensi untuk Praktisi Berpikir (tidak ada kutipan online, maaf):
sumber
NULL
bukan nilai.(NULL = NULL) -> FALSE
. Mengutip dokumentasi untukANSI_NULLS
: "Ketika ON ditentukan, semua perbandingan dengan nilai nol mengevaluasi ke UNKNOWN . Ketika OFF ditentukan, perbandingan nilai non-UNICODE ke nilai nol mengevaluasi ke TRUE jika kedua nilai tersebut NULL."Mungkin itu tergantung, tapi saya pikir
NULL=NULL
mengevaluasiNULL
menyukai sebagian besar operasi dengan NULL sebagai operan.sumber
Hanya karena Anda tidak tahu apa dua hal itu, tidak berarti keduanya sama. Jika ketika Anda memikirkan
NULL
Anda memikirkan "NULL" (string) maka Anda mungkin ingin tes kesetaraan yang berbeda seperti PostgresqlIS DISTINCT FROM
DANIS NOT DISTINCT FROM
Dari dokumen PostgreSQL tentang "Fungsi dan Operator Perbandingan"
sumber
Konsep NULL dipertanyakan, untuk sedikitnya. Codd memperkenalkan model relasional dan konsep NULL dalam konteks (dan kemudian mengusulkan lebih dari satu jenis NULL!) Namun, teori relasional telah berkembang sejak tulisan asli Codd: beberapa proposal sejak itu telah dibatalkan (misalnya kunci primer) dan yang lain tidak pernah tertangkap (mis. operator theta). Dalam teori relasional modern (benar-benar teori relasional, saya harus menekankan) NULL sama sekali tidak ada. Lihat Manifesto Ketiga. http://www.thethirdmanifesto.com/
Bahasa SQL menderita masalah kompatibilitas mundur. NULL menemukan jalannya ke SQL dan kami terjebak dengannya. Bisa dibilang, implementasi
NULL
dalam SQL cacat (implementasi SQL Server membuat hal-hal lebih rumit karenaANSI_NULLS
pilihannya).Saya sarankan menghindari penggunaan kolom NULLable di tabel dasar.
Meskipun mungkin saya tidak boleh tergoda, saya hanya ingin menegaskan koreksi saya sendiri tentang cara
NULL
kerjanya di SQL:NULL
=NULL
dievaluasi untukUNKNOWN
.UNKNOWN
adalah nilai logis.NULL
adalah nilai data.Ini mudah untuk dibuktikan misalnya
SELECT NULL = NULL
dengan benar menghasilkan kesalahan dalam SQL Server. Jika hasilnya adalah nilai data maka kita akan mengharapkan untuk melihat
NULL
, karena beberapa jawaban di sini (salah) menyarankan kita.Nilai logis
UNKNOWN
diperlakukan secara berbeda dalam SQL DML dan SQL DDL.Dalam SQL DML,
UNKNOWN
menyebabkan baris dihapus dari resultset.Sebagai contoh:
The
INSERT
berhasil untuk baris ini, meskipunCHECK
kondisi memutuskan untukNULL = NULL
. Ini karena didefinisikan dalam Standar SQL-92 ("ANSI"):Baca lagi dengan cermat, ikuti logika.
Dalam bahasa Inggris sederhana, baris baru kami di atas diberi 'manfaat keraguan' tentang menjadi
UNKNOWN
dan diizinkan untuk berlalu.Dalam SQL DML, aturan untuk
WHERE
klausa jauh lebih mudah diikuti:Dalam bahasa Inggris biasa, baris yang mengevaluasi untuk
UNKNOWN
dihapus dari resultset.sumber
Di technet ada penjelasan yang bagus untuk cara kerja nilai null.
Null berarti tidak dikenal.
Karena itulah ungkapan Boolean
nilai = nol
tidak mengevaluasi ke false, itu mengevaluasi ke nol, tetapi jika itu adalah hasil akhir dari klausa di mana, maka tidak ada yang dikembalikan. Itu adalah cara praktis untuk melakukannya, karena mengembalikan nol akan sulit dipahami.
Sangat menarik dan sangat penting untuk memahami hal-hal berikut:
Jika dalam query kita punya
dan
kemudian
"value = @ param" dievaluasi menjadi null
"@param is null" dievaluasi ke true
"id = @ anotherParam" dievaluasi menjadi true
Jadi ungkapan yang akan dievaluasi menjadi
(null Atau benar) Dan benar
Kita mungkin tergoda untuk berpikir bahwa di sini "null or true" akan dievaluasi menjadi nol dan dengan demikian seluruh ekspresi menjadi nol dan baris tidak akan dikembalikan.
Ini tidak benar. Mengapa?
Karena "null Atau true" mengevaluasi ke true, yang sangat logis, karena jika satu operan benar dengan operator-Or, maka tidak peduli nilai operan lainnya, operasi akan mengembalikan true. Dengan demikian tidak masalah bahwa operan lainnya tidak dikenal (nol).
Jadi kita akhirnya memiliki true = true dan dengan demikian baris akan dikembalikan.
Catatan: dengan logika jernih yang sama dengan "null or true" dievaluasi menjadi true, "null And true" dievaluasi menjadi null.
Pembaruan:
Ok, hanya untuk menyelesaikannya Saya ingin menambahkan sisanya di sini juga yang ternyata cukup menyenangkan sehubungan dengan di atas.
"null or false" dievaluasi menjadi null, "null And false" dievaluasi menjadi false. :)
Logikanya tentu saja masih jelas seperti sebelumnya.
sumber
Karena
NULL
berarti 'nilai tidak diketahui' dan dua nilai tidak diketahui tidak boleh sama.Jadi, jika untuk logika kita,
NULL
N ° 1 sama denganNULL
N ° 2, maka kita harus mengatakannya:di mana nilai yang diketahui
-1
N ° 1 sama dengan-1
N ° 2sumber
nullParam1 = -1
dannullParam2 =NULL
dan kecelakaan pesawat .... harusISNULL(NULLIF(@nullParam1, @nullParam2), NULLIF(@nullParam2, nullParam1)) IS NULL
Semua jawaban di sini tampaknya berasal dari perspektif CS, jadi saya ingin menambahkannya dari perspektif pengembang.
Untuk pengembang, NULL sangat berguna. Jawaban di sini mengatakan NULL berarti tidak diketahui, dan mungkin dalam teori CS itu benar, tidak ingat, sudah lama. Dalam perkembangan aktual, setidaknya dalam pengalaman saya, itu terjadi sekitar 1% dari waktu. 99% lainnya digunakan untuk kasus-kasus di mana nilainya tidak DIKETAHUI tetapi DIKETAHUI UNTUK MENJADI ABSEN.
Sebagai contoh:
Client.LastPurchase
, untuk klien baru. Bukan tidak diketahui, diketahui bahwa dia belum melakukan pembelian.Saat menggunakan ORM dengan Table per Class Hierarchy mapping, beberapa nilai tidak dipetakan untuk kelas tertentu.
Saat memetakan struktur pohon, biasanya root memiliki
Parent = NULL
Dan masih banyak lagi...
Saya yakin sebagian besar pengembang menulis
WHERE value = NULL
, tidak mendapatkan hasil apa pun, dan itulah cara mereka mempelajariIS NULL
sintaksis. Lihat saja berapa banyak suara yang dimiliki pertanyaan ini dan yang tertaut.Database SQL adalah alat, dan mereka harus dirancang dengan cara yang paling mudah bagi pengguna untuk memahaminya.
sumber
NULL tidak sama dengan apa pun, bahkan untuk dirinya sendiri. Solusi pribadi saya untuk memahami perilaku NULL adalah menghindari menggunakannya semaksimal mungkin :).
sumber
Pertanyaannya:
Apakah satu yang tidak dikenal sama dengan yang tidak diketahui lainnya?
(NULL = NULL)
Pertanyaan itu adalah sesuatu yang tidak bisa dijawab oleh siapa pun sehingga default ke true atau false tergantung pada pengaturan ansi_nulls Anda.
Namun pertanyaannya:
Apakah variabel yang tidak dikenal ini tidak diketahui?
Pertanyaan ini sangat berbeda dan dapat dijawab dengan benar.
nullVariable = null membandingkan nilai-nilai
nullVariable adalah null membandingkan keadaan variabel
sumber
Kebingungan muncul dari tingkat tipuan (abstraksi) yang muncul karena menggunakan NULL .
Kembali ke analogi "apa yang ada di bawah pohon Natal", "Tidak Dikenal" menggambarkan keadaan pengetahuan tentang apa yang ada di Kotak A.
Jadi jika Anda tidak tahu apa yang ada di Kotak A, Anda mengatakan itu "Tidak Dikenal", tetapi itu tidak berarti bahwa "Tidak Dikenal" ada di dalam kotak . Sesuatu selain yang tidak dikenal ada di dalam kotak, mungkin semacam objek, atau mungkin tidak ada yang ada di dalam kotak.
Demikian pula, jika Anda tidak tahu apa yang ada di Kotak B, Anda dapat memberi label status pengetahuan Anda tentang konten sebagai "Tidak Dikenal".
Jadi tau nggak: Anda negara pengetahuan tentang Box A sama dengan negara Anda pengetahuan tentang Box B . (Keadaan pengetahuan Anda dalam kedua kasus adalah "Tidak Diketahui" atau "Saya tidak tahu apa yang ada di dalam Kotak".) Tetapi isi kotak mungkin atau mungkin tidak sama.
Kembali ke SQL, idealnya Anda hanya dapat membandingkan nilai ketika Anda tahu apa itu. Sayangnya, label yang menggambarkan kurangnya pengetahuan disimpan dalam sel itu sendiri , jadi kami tergoda untuk menggunakannya sebagai nilai. Tetapi kita tidak boleh menggunakan itu sebagai nilai, karena itu akan mengarah pada "isi Kotak A sama dengan isi Kotak B ketika kita tidak tahu apa yang ada di Kotak A dan / atau kita tidak tahu apa yang ada di Kotak B. (Logikanya, implikasinya "jika saya tidak tahu apa yang ada di Kotak A dan jika saya tidak tahu apa yang ada di Kotak B, maka apa yang ada di Kotak A = Apa yang ada di Kotak B" adalah salah.)
Yay, Kuda Mati.
sumber
MSDN memiliki artikel deskriptif yang bagus tentang nulls dan logika tiga negara yang mereka hasilkan.
Singkatnya, spesifikasi SQL92 mendefinisikan NULL sebagai tidak diketahui, dan NULL yang digunakan dalam operator berikut menyebabkan hasil yang tidak terduga untuk yang belum tahu:
sumber
null tidak dikenal di sql jadi kami tidak bisa berharap dua yang tidak diketahui sama.
Namun Anda bisa mendapatkan perilaku itu dengan mengatur ANSI_NULLS ke Mati (Nyala secara Default) Anda akan dapat menggunakan = operator untuk nol
sumber
null
, belajar memahaminya atau hanya mengubah tabel untuk memiliki tipe int dan memperbarui kolom.Anda bekerja untuk pemerintah yang mendaftarkan informasi tentang warga. Ini termasuk ID nasional untuk setiap orang di negara ini. Seorang anak ditinggalkan di pintu gereja sekitar 40 tahun yang lalu, tidak ada yang tahu siapa orang tua mereka. ID ayah orang ini adalah
NULL
. Dua orang seperti itu ada. Hitung orang yang memiliki ID ayah yang sama dengan setidaknya satu orang lain (orang yang bersaudara). Apakah Anda menghitung keduanya juga?Jawabannya adalah tidak, Anda tidak tahu, karena kami tidak tahu apakah mereka bersaudara atau tidak.
Misalkan Anda tidak memiliki
NULL
pilihan, dan alih-alih menggunakan beberapa nilai yang ditentukan sebelumnya untuk mewakili "yang tidak diketahui", mungkin string kosong atau angka 0 atau karakter *, dll. Maka Anda akan memiliki dalam pertanyaan Anda bahwa * = * , 0 = 0, dan “” = “”, dll. Ini bukan yang Anda inginkan (seperti contoh di atas), dan karena Anda mungkin sering lupa tentang kasus-kasus ini (contoh di atas adalah kasus pinggiran yang jelas di luar pemikiran sehari-hari yang biasa ), maka Anda perlu mengingat bahasa untuk Anda yangNULL = NULL
tidak benar.Kebutuhan adalah ibu dari penemuan.
sumber
Hanya tambahan untuk jawaban luar biasa lainnya:
sumber
Jika Anda mencari ekspresi yang menghasilkan true untuk dua NULL, Anda dapat menggunakan:
Akan sangat membantu jika Anda ingin mereplikasi data dari satu tabel ke tabel lainnya.
sumber
Tes kesetaraan, misalnya, dalam pernyataan kasus ketika klausa, dapat diubah dari
untuk
Jika saya ingin memperlakukan string kosong dan kosong sama dengan NULL, saya sering juga menggunakan tes kesetaraan seperti:
sumber