Mengapa NULL = NULL dievaluasi menjadi false di SQL server

147

Di SQL server jika Anda memiliki nullParam=NULLklausa where, ia selalu bernilai false. Ini berlawanan dengan intuisi dan telah menyebabkan saya banyak kesalahan. Saya mengerti IS NULLdan IS NOT NULLkata kunci adalah cara yang tepat untuk melakukannya. Tetapi mengapa SQL server berperilaku seperti ini?

Byron Whitlock
sumber
166
Saya tidak punya saudara perempuan, dan teman saya juga tidak. Jika "NULL = NULL" maka kita memiliki saudara perempuan yang sama, dan karena itu terkait! :)
Matt Hamilton
11
Ada kontroversi yang berjalan lama pada SQL NULLs (lihat misalnya: en.wikipedia.org/wiki/Null_%28SQL%29#Controversy dan firstsql.com/inulls.htm ). Poin spesifik di sini adalah bahwa kesetaraan adalah konsep matematika yang telah lama didirikan dan SQL melanggarnya - kesetaraan bersifat refleksif: untuk setiap x, x = x. Itu harus selalu benar, kalau tidak, orang akan memperkenalkan interpretasi kesetaraan yang tidak standar dan kebingungan adalah hasil yang jelas.
MaD70
14
Itu tidak melanggar matematika sama sekali. Saya sedang memikirkan dua angka. Aku tidak akan memberitahumu apa itu. Jadi sekarang Anda memberi tahu saya, apakah mereka sama?
Tom H
10
@ Mat, saya tidak setuju dengan analogi Anda. NULL = NULL tidak berarti Anda memiliki saudara perempuan yang sama, itu berarti Anda berdua tidak memiliki saudara perempuan.
reustmd
5
@ manu08 Tidak, implementasi saat ini (bahwa NULL tidak pernah sama dengan NULL) berarti bahwa kami berdua tidak memiliki saudara perempuan, yang merupakan poin saya.
Matt Hamilton

Jawaban:

206

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 ...

set ansi_nulls off

if null = null
    print 'true'
else
    print 'false'


set ansi_nulls ON

if null = null
    print 'true'
else
    print 'false'
Scott Ivey
sumber
11
x = x hanya berlaku ketika x adalah nilai yang diketahui . NULL adalah representasi tekstual dari nilai yang tidak diketahui . Jika Anda memiliki dua nilai yang tidak diketahui, Anda tidak dapat secara konklusif menyatakan apa pun tentang kesetaraannya. Saya percaya hal itu juga berlaku selama beberapa abad.
Dewayne Christensen
4
Karena ini bulan Desember, mari kita gunakan contoh musiman. Saya punya dua hadiah di bawah pohon. Sekarang, katakan padaku apakah saya mendapat dua hal yang sama atau tidak.
Dewayne Christensen
5
SQL NULL tidak berbeda dengan floating point IEEE NaN, di mana Anda juga memiliki (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.
Pavel Minaev
8
Tidak ada pelanggaran refleksivitas di sini, karena NULL bukan anggota dari himpunan nilai (domain, dalam istilah relasional). NULL bukan nilai . Ini pengganti untuk nilai yang tidak diketahui.
Pavel Minaev
9
Dengan kata lain, setiap NULLekspresi SQL dapat diperlakukan sebagai variabel matematika yang berbeda . Jadi ekspresi NULL = NULLharus diperlakukan sebagai x = y, di mana xdan ymerupakan variabel tidak terikat. Sekarang jika seseorang bertanya kepada Anda, apa nilainya x = y? Satu-satunya jawaban yang masuk akal adalah, "beberapa z". Jadi kami telah (x = y) = z- atau, menyalinnya kembali ke SQL (NULL = NULL) = NULL,.
Pavel Minaev
131

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.

Neil McGuigan
sumber
4
Saya tidak setuju bahwa nol menandakan "tidak dikenal". Apa artinya sebenarnya adalah "tidak ada data". Itu mungkin digunakan untuk mewakili kasus di mana informasi tidak diketahui, tetapi sebenarnya lebih cenderung digunakan untuk menunjukkan bahwa sesuatu tidak ada. Untuk melanjutkan contoh Anda: Apa nama tengah Frank? Dia tidak punya satu (nol). Apa nama tengah Shirley? Dia tidak punya satu (nol). Apakah Frank dan Shirley memiliki nama tengah yang sama? Iya? Tidak? Tidak tahu Saya bisa melihat argumen untuk "tidak", dan saya bisa melihat argumen untuk "tidak tahu", tetapi tidak ada argumen nyata untuk "ya" kecuali Anda terlalu harfiah.
Richiban
2
@ Richiban saya tidak setuju. Kurangnya keberadaan baris berarti 'tidak ada data'
Neil McGuigan
1
@NeilMcGuigan Benar jika untuk data yang memiliki tabel sendiri, tetapi bagaimana dengan data yang direpresentasikan dalam kolom? Tidakkah Anda menggunakan 'null' untuk mewakili fakta bahwa data tidak ada? 'Tidak dikenal' adalah alasan yang sangat spesifik untuk ketidakhadiran data.
Richiban
3
Tapi null = nullhasil FALSE, bukan NULL.
slartidan
1
@slartidan saya setuju dengan Anda, namun itu tidak benar
Neil McGuigan
28

Di sini saya mudah-mudahan akan memperjelas posisi saya.

Yang NULL = NULLmengevaluasi untuk FALSEsalah. Peretas dan Tuan menjawab dengan benar NULL. Inilah sebabnya. Dewayne Christensen menulis kepada saya, dalam komentar untuk Scott Ivey :

Karena ini bulan Desember, mari kita gunakan contoh musiman. Saya punya dua hadiah di bawah pohon. Sekarang, katakan padaku apakah saya mendapat dua hal yang sama atau tidak.

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 ".. ( falseatau null, tergantung pada sistem Anda) .." adalah jawaban yang benar - bukan, hanya NULL 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:

  • Logika tiga nilai (3VL) adalah berlawanan dengan intuisi (lihat pertanyaan lain yang tak terhitung jumlahnya tentang subjek ini di Stackoverflow dan di forum lain untuk memastikan);
  • DBMSes berbasis SQL sering tidak menghargai bahkan 3VL, mereka kadang-kadang memberikan jawaban yang salah (seperti yang dinyatakan oleh poster asli, SQL Server lakukan dalam kasus ini).

Jadi saya ulangi: SQL tidak ada gunanya memaksa orang untuk menafsirkan properti refleksif kesetaraan, yang menyatakan bahwa:

for any x, x = x §§ (dalam bahasa Inggris yang sederhana: apa pun alam semesta wacana, "sesuatu" selalu sama dengan dirinya sendiri ).

.. dalam 3VL ( TRUE, FALSE, NULL). Harapan orang akan sesuai dengan 2VL ( TRUE,, FALSEyang bahkan dalam SQL berlaku untuk semua nilai lainnya), yaitu x = x selalu dievaluasi untuk TRUE , 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:

3.4 Aritmatika dan
NULL 109 3.5 Nilai Konversi ke dan dari NULL 110
3.5.1 NULLIF () Fungsi 110
6 NULL : Data yang Hilang dalam SQL 185
6.4 Membandingkan NULLs 190
6.5 NULLs dan Logic 190
6.5.1 NULLS dalam Predikat Subquery 191
6.5.2 Standar Solusi SQL 193
6.6 Matematika dan NULL 193
6.7 Fungsi dan NULL 193
6.8 NULLs dan Bahasa Host 194
6.9 Nasihat Desain untuk NULLs 195
6.9.1 Menghindari
NULL dari Program Host 197 6.10 Catatan tentang Beberapa Nilai NULL 198
10.1 IS NULL Predikat 241
10.1. 1 Sumber NULLs 242
...

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.

NOT NULL Constraint (11)

Batasan kolom yang paling penting adalah NOT NULL, yang melarang penggunaan NULLs dalam kolom. Gunakan batasan ini secara rutin, dan hapus hanya ketika Anda memiliki alasan yang bagus. Ini akan membantu Anda menghindari komplikasi dari nilai NULL ketika Anda membuat pertanyaan terhadap data.

Itu bukan nilai ; itu adalah penanda yang memegang tempat di mana nilai mungkin pergi.

Lagi-lagi ini "nilai tetapi tidak cukup nilai" omong kosong. Sisanya tampaknya cukup masuk akal bagi saya.

(12)

Singkatnya, NULLs menyebabkan banyak fitur tidak beraturan dalam SQL, yang akan kita bahas nanti. Taruhan terbaik Anda adalah hanya menghafal situasi dan aturan untuk NULL ketika Anda tidak bisa menghindarinya.

Sepenuhnya dari SQL, NULLs dan infinite:

(104) BAB 3: DATA NUMERIK DALAM SQL

SQL belum menerima model IEEE untuk matematika karena beberapa alasan.

...

Jika aturan IEEE untuk matematika diizinkan dalam SQL, maka kita perlu mengetikkan aturan konversi untuk tak terbatas dan cara untuk mewakili nilai numerik persis tak terhingga setelah konversi. Orang-orang memiliki cukup masalah dengan NULLs, jadi jangan pergi ke sana.

Implementasi SQL ragu-ragu tentang apa arti sebenarnya NULL dalam konteks tertentu:

3.6.2 Fungsi Eksponensial (116)

Masalahnya adalah logaritma tidak terdefinisi kapan (x <= 0). Beberapa implementasi SQL mengembalikan pesan kesalahan, beberapa mengembalikan NULL dan DB2 / 400; versi 3 rilis 1 kembali * NEGINF (kependekan dari "infinity negatif") sebagai hasilnya.

Joe Celko mengutip David McGoveran dan CJ Date:

6 NULLs: Data yang Hilang dalam SQL (185)

Dalam buku mereka A Guide to Sybase dan SQL Server , David McGoveran dan CJ Date mengatakan: “Ini adalah pendapat penulis ini daripada NULLs, setidaknya seperti yang didefinisikan dan diimplementasikan saat ini dalam SQL, jauh lebih banyak masalah daripada nilainya dan harus dihindari; mereka menampilkan perilaku yang sangat aneh dan tidak konsisten dan bisa menjadi sumber kesalahan dan kebingungan yang kaya. (Harap dicatat bahwa komentar dan kritik ini berlaku untuk sistem apa pun yang mendukung NULL gaya SQL, tidak hanya untuk SQL Server secara khusus.) ”

NULL sebagai kecanduan narkoba :

(186/187)

Di sisa buku ini, saya akan mendesak Anda untuk tidak menggunakannya , yang mungkin tampak kontradiktif, tetapi tidak. Pikirkan NULL sebagai obat; gunakan dengan benar dan itu bekerja untuk Anda, tetapi menyalahgunakannya dan itu dapat merusak segalanya. Kebijakan terbaik Anda adalah untuk menghindari NULL ketika Anda bisa dan menggunakannya dengan benar ketika Anda harus.

Keberatan unik saya di sini adalah untuk "menggunakannya dengan benar", yang berinteraksi buruk dengan perilaku implementasi tertentu.

6.5.1 NULLS dalam Predikat Subquery (191/192)

Orang-orang lupa bahwa subquery sering menyembunyikan perbandingan dengan NULL. Pertimbangkan dua tabel ini:

...

Hasilnya akan kosong. Ini berlawanan dengan intuisi , tetapi benar.

(pemisah)

6.5.2 Solusi SQL Standar (193)

SQL-92 memecahkan beberapa masalah 3VL (logika tiga-nilai) dengan menambahkan predikat baru dari formulir:

<kondisi pencarian> IS [BUKAN] BENAR | SALAH | TIDAK DIKENAL

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 :

  • Jangan gunakan kata kunci TIDAK DIKETAHUI dalam konteks apa pun.

Baca "ASIDE" di UNKNOWN, juga terhubung di bawah ini.

6.8 NULL dan Bahasa Inang (194)

Namun, Anda harus tahu bagaimana NULL ditangani ketika harus diteruskan ke program host. Tidak ada bahasa host standar yang mendefinisikan embedding mendukung NULLs, yang merupakan alasan bagus untuk menghindari menggunakannya dalam skema basis data Anda.

(pemisah)

6.9 Saran Desain untuk NULLs (195)

Merupakan ide bagus untuk mendeklarasikan semua tabel dasar Anda dengan batasan TIDAK NULL pada semua kolom bila memungkinkan. NULL membingungkan orang-orang yang tidak tahu SQL, dan NULL mahal.

Keberatan: NULLs membingungkan bahkan orang yang mengenal SQL dengan baik, lihat di bawah.

(195)

NULL harus dihindari dalam KUNCI ASING. SQL memungkinkan hubungan "manfaat keraguan" ini, tetapi dapat menyebabkan hilangnya informasi dalam kueri yang melibatkan gabungan. Misalnya, diberi kode nomor bagian dalam Inventaris yang direferensikan sebagai KUNCI LUAR NEGERI oleh tabel Pesanan, Anda akan mengalami masalah dalam mendapatkan daftar bagian yang memiliki NULL. Ini adalah hubungan wajib; Anda tidak dapat memesan bagian yang tidak ada.

(pemisah)

6.9.1 Menghindari NULL dari Program Host (197)

Anda dapat menghindari memasukkan NULL ke dalam database dari Program Host dengan beberapa disiplin pemrograman.

...

  1. Tentukan dampak dari data yang hilang pada pemrograman dan pelaporan: Kolom angka dengan NULL adalah masalah, karena kueri yang menggunakan fungsi agregat dapat memberikan hasil yang menyesatkan.

(pemisah)

(227)

SUM () dari set kosong selalu NULL. Salah satu kesalahan pemrograman paling umum yang dibuat saat menggunakan trik ini adalah menulis kueri yang bisa mengembalikan lebih dari satu baris. Jika Anda tidak memikirkannya, Anda mungkin telah menulis contoh terakhir sebagai: ...

(pemisah)

10.1.1 Sumber NULLs (242)

Penting untuk mengingat di mana NULL dapat terjadi. Mereka lebih dari sekadar nilai yang mungkin dalam kolom . Fungsi agregat pada set kosong, GABUNGAN LUAR, ekspresi aritmatika dengan NULLs, dan operator OLAP semua mengembalikan NULLs. Konstruk ini sering ditampilkan sebagai kolom di LIHAT.

(pemisah)

(301)

Masalah lain dengan NULLs ditemukan ketika Anda mencoba untuk mengkonversi predikat IN ke predikat EXISTS.

(pemisah)

16.3 SEMUA Predikat dan Fungsi Ekstrem (313)

Ini berlawanan dengan intuisi pada awalnya bahwa kedua predikat ini tidak sama dalam SQL:

...

Tetapi Anda harus mengingat aturan untuk fungsi ekstrema — mereka menghapus semua NULL sebelum mengembalikan nilai yang lebih besar atau paling kecil. SEMUA predikat tidak menjatuhkan NULL, sehingga Anda bisa mendapatkannya di hasil.

(pemisah)

(315)

Namun, definisi dalam standar dituliskan dalam negatif, sehingga NULL mendapatkan manfaat dari keraguan. ...

Seperti yang Anda lihat, itu adalah ide yang baik untuk menghindari NULL dalam batasan UNIK.

Membahas GROUP BY:

NULL diperlakukan seolah-olah mereka semua sama satu sama lain , dan membentuk grup mereka sendiri. Setiap grup kemudian direduksi menjadi satu baris dalam tabel hasil baru yang menggantikan yang lama.

Ini berarti bahwa untuk GROUP BY klausa NULL = NULL tidak mengevaluasi ke NULL, seperti pada 3VL, tetapi mengevaluasi ke BENAR.

Standar SQL membingungkan:

ORDER BY dan NULLs (329)

Apakah nilai kunci pengurutan yang NULL dianggap lebih besar atau kurang dari nilai non-NULL ditentukan oleh implementasi, tetapi ...

... Ada produk SQL yang melakukannya dengan cara baik.

Pada bulan Maret 1999, Chris Farrar mengajukan pertanyaan dari salah satu pengembangnya yang menyebabkan dia memeriksa bagian dari Standar SQL yang saya pikir saya mengerti . Chris menemukan beberapa perbedaan antara pemahaman umum dan kata-kata sebenarnya dari spesifikasi .

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

10.3 Implikasi Praktis

10.3.1 SQL NULLs

... SQL menderita dari masalah yang melekat pada 3VL serta dari banyak kebiasaan, komplikasi, berlawanan dengan intuisi, dan kesalahan langsung [10, 11]; di antara mereka adalah sebagai berikut:

  • Fungsi agregat (misalnya, SUM (), AVG ()) mengabaikan NULLs (kecuali untuk COUNT ()).
  • Ekspresi skalar pada tabel tanpa baris mengevaluasi dengan salah untuk NULL, bukan 0.
  • Ekspresi "NULL = NULL" mengevaluasi ke NULL, tetapi sebenarnya tidak valid dalam SQL; namun ORDER BY memperlakukan NULLs sebagai sama (apa pun yang mereka mendahului atau mengikuti nilai-nilai "reguler" diserahkan kepada vendor DBMS).
  • Ekspresi "x IS NOT NULL" tidak sama dengan "NOT (x IS NULL)", seperti halnya dalam 2VL.

...

Semua dialek SQL yang diimplementasikan secara komersial mengikuti pendekatan 3VL ini, dan, dengan demikian, mereka tidak hanya menyelesaikan masalah ini, tetapi mereka juga memiliki masalah implementasi spefic, yang bervariasi di seluruh produk .

rev MaD70
sumber
4
"Dan ini poin saya: NULL, sebagai nilai, adalah" binatang aneh "." - itu karena NULLbukan nilai.
Pavel Minaev
1
Juga, SQL Server tidak memberi (NULL = NULL) -> FALSE. Mengutip dokumentasi untuk ANSI_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."
Pavel Minaev
@Pavel Minaev: a) dan bagaimana BENAR lebih baik daripada SALAH? b) Jika bukan nilai mengapa ditugaskan sebagai bagian dari nilai variabel?
MaD70
1
>> Karena ini bulan Desember, mari kita gunakan contoh musiman. Saya punya dua hadiah di bawah pohon. Sekarang, katakan padaku apakah saya mendapat dua hal yang sama atau tidak. ..... ya, Anda melakukan sejauh yang Anda dapatkan dua hal dan sejauh yang Anda ketahui saat ini , sejauh pengetahuan Anda saat ini, mereka persis sama untuk Anda
Brad Thomas
3
null = null harus benar. null nilai yang mungkin terdefinisi dengan baik mewakili suatu yang tidak diketahui nilai, tetapi juga dapat mewakili para adanya nilai. Seharusnya tergantung pada pengembang untuk memutuskan apa yang null wakili, tetapi nol itu sendiri benar-benar nilai dan null adalah nol = nol. Implementasi lainnya pasti akan mengalami bencana, karena Anda menyisipkan logika terner ke predikat yang pada dasarnya adalah Boolean. Saya SELALU bahwa ini menjadi permanen pada pengaturan di SQL server. OFF OFF OFF dengan itu.
Triynko
9

Mungkin itu tergantung, tapi saya pikir NULL=NULLmengevaluasi NULLmenyukai sebagian besar operasi dengan NULL sebagai operan.

Michael Krelin - hacker
sumber
9

Hanya karena Anda tidak tahu apa dua hal itu, tidak berarti keduanya sama. Jika ketika Anda memikirkan NULLAnda memikirkan "NULL" (string) maka Anda mungkin ingin tes kesetaraan yang berbeda seperti Postgresql IS DISTINCT FROMDANIS NOT DISTINCT FROM

Dari dokumen PostgreSQL tentang "Fungsi dan Operator Perbandingan"

ekspresi IS DISTINCT FROMekspresi

ekspresi IS NOT DISTINCT FROMekspresi

Untuk input yang bukan nol, IS DISTINCT FROMsama dengan <>operator. Namun, jika kedua input adalah null, ia mengembalikan false, dan jika hanya satu input yang kosong, ia mengembalikan true. Demikian pula, IS NOT DISTINCT FROMidentik dengan =untuk input non-null, tetapi mengembalikan true ketika kedua input adalah null, dan false ketika hanya satu input yang nol. Dengan demikian, konstruksi ini secara efektif bertindak seolah-olah nol adalah nilai data normal, bukan "tidak dikenal".

Evan Carroll
sumber
5

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 NULLdalam SQL cacat (implementasi SQL Server membuat hal-hal lebih rumit karena ANSI_NULLSpilihannya).

Saya sarankan menghindari penggunaan kolom NULLable di tabel dasar.


Meskipun mungkin saya tidak boleh tergoda, saya hanya ingin menegaskan koreksi saya sendiri tentang cara NULLkerjanya di SQL:

NULL= NULLdievaluasi untuk UNKNOWN.

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 UNKNOWNdiperlakukan secara berbeda dalam SQL DML dan SQL DDL.

Dalam SQL DML, UNKNOWNmenyebabkan baris dihapus dari resultset.

Sebagai contoh:

CREATE TABLE MyTable
(
 key_col INTEGER NOT NULL UNIQUE, 
 data_col INTEGER
 CHECK (data_col = 55)
);

INSERT INTO MyTable (key_col, data_col)
   VALUES (1, NULL);

The INSERTberhasil untuk baris ini, meskipun CHECKkondisi memutuskan untuk NULL = NULL. Ini karena didefinisikan dalam Standar SQL-92 ("ANSI"):

11.6 definisi batasan tabel

3)

Jika batasan tabel adalah definisi batasan periksa, maka biarkan SC menjadi kondisi pencarian yang langsung terkandung dalam definisi batasan periksa dan misalkan T adalah nama tabel yang termasuk dalam deskriptor kendala tabel terkait; batasan tabel tidak puas jika dan hanya jika

ADA (SELECT * DARI T WHERE NOT (SC))

adalah benar.

Baca lagi dengan cermat, ikuti logika.

Dalam bahasa Inggris sederhana, baris baru kami di atas diberi 'manfaat keraguan' tentang menjadi UNKNOWNdan diizinkan untuk berlalu.

Dalam SQL DML, aturan untuk WHEREklausa jauh lebih mudah diikuti:

Kondisi pencarian diterapkan ke setiap baris T. Hasil dari klausa di mana adalah tabel dari baris-baris T yang hasilnya benar.

Dalam bahasa Inggris biasa, baris yang mengevaluasi untuk UNKNOWNdihapus dari resultset.

suatu hari nanti
sumber
5

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

where (value=@param Or @param is null) And id=@anotherParam

dan

  • nilai = 1
  • @param adalah nol
  • id = 123
  • @ anotherParam = 123

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.

Magnus
sumber
4

Karena NULLberarti 'nilai tidak diketahui' dan dua nilai tidak diketahui tidak boleh sama.

Jadi, jika untuk logika kita, NULLN ° 1 sama dengan NULLN ° 2, maka kita harus mengatakannya:

SELECT 1
WHERE ISNULL(nullParam1, -1) = ISNULL(nullParam2, -1)

di mana nilai yang diketahui -1N ° 1 sama dengan -1N ° 2

Armen
sumber
nullParam1 = -1dan nullParam2 =NULLdan kecelakaan pesawat .... harusISNULL(NULLIF(@nullParam1, @nullParam2), NULLIF(@nullParam2, nullParam1)) IS NULL
Selvin
4

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 memilikiParent = NULL

  • Dan masih banyak lagi...

Saya yakin sebagian besar pengembang menulis WHERE value = NULL, tidak mendapatkan hasil apa pun, dan itulah cara mereka mempelajari IS NULLsintaksis. 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.

AlexDev
sumber
1
Semua orang sepertinya berteriak "NULL tidak dikenal" dan kemudian membenarkan perilakunya. Ya, jika itu adalah premis maka 3VL mungkin jawabannya. Tetapi di hampir semua DB yang saya garap, NULL berarti absen. Maaf suara Anda hilang di hutan belantara @AlexDev
John Rees
3

NULL tidak sama dengan apa pun, bahkan untuk dirinya sendiri. Solusi pribadi saya untuk memahami perilaku NULL adalah menghindari menggunakannya semaksimal mungkin :).

Chris R. Timmons
sumber
1
mungkin juga sama untuk segala sesuatu, seperti dalam kasus kiri / kanan / luar bergabung ...
Miguel Ventura
5
Jawaban yang konyol dan tidak produktif. Hal yang sama bisa dikatakan kepada anak-anak sekolah dasar tentang aljabar, tetapi tanpa benar-benar mengakui apa yang sedang berusaha menyelesaikannya, itu akan terasa konyol, dan memang demikian.
Evan Carroll
2
@ Evan: Sebenarnya, menghindari NULL adalah solusi yang bagus. Logika 3-dihargai bukan tidak kontroversial, dan banyak orang merasa bahwa SQL akan lebih baik tanpa NULL dan semua kompleksitas yang diperlukan.
sleske
3
"Banyak orang" adalah kata musang, dan "bukan tidak kontroversial" adalah cara untuk menyelubungi "kontroversial" yang lebih sederhana yang 3VL tidak.
Evan Carroll
"NULL tidak sama dengan apa pun, bahkan untuk dirinya sendiri." menggunakan logika itu, <somevalue>! = NULL harus mengembalikan true. Namun, di alam semesta SQL yang aneh, itu salah.
Tom Lint
3

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

pengguna224385
sumber
3

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.

TomEberhard
sumber
3

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:

= operator NULL   true   false 
NULL       NULL   NULL   NULL
true       NULL   true   false
false      NULL   false  true

and op     NULL   true   false 
NULL       NULL   NULL   false
true       NULL   true   false
false      false  false  false

or op      NULL   true   false 
NULL       NULL   true   NULL
true       true   true   true
false      NULL   true   false
Paul Wagland
sumber
Tetapi pertanyaannya bukan tentang 3VL (logika tiga nilai) adalah tentang sifat refleksif dari kesetaraan.
MaD70
Untuk lebih tepatnya, seperti yang akhirnya saya jelaskan dalam jawaban saya, masalah muncul ketika kesetaraan ditafsirkan dalam 3VL sehingga properti refleksif dari kesetaraan tidak selalu dievaluasi menjadi benar.
MaD70
1

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

SET ANSI_NULLS off
if null=null
print 1
else 
print 2
set ansi_nulls on
if null=null
print 1
else 
print 2
ps.
sumber
2
Ini semua jenis no . Dunia memiliki definisi null, belajar memahaminya atau hanya mengubah tabel untuk memiliki tipe int dan memperbarui kolom.
Evan Carroll
3
Saya benar-benar tidak merekomendasikan untuk menonaktifkan SET ANSI_NULLS. Saya mengetahui tentang ANSI_NULLS dengan cara yang sulit. Tetapi selalu baik untuk mengetahui semua opsi yang tersedia secara khusus ketika Anda menemukan sebuah baris yang mengatakan Di mana SomeId = null Bagaimana Anda memahami garis itu tanpa mengetahui tentang ANSI_NULLS. Cara saya melihatnya, posting saya bermanfaat .. :)
ps.
1

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 NULLpilihan, 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 yang NULL = NULLtidak benar.

Kebutuhan adalah ibu dari penemuan.

Rashad Saleh
sumber
0

Hanya tambahan untuk jawaban luar biasa lainnya:

AND: The result of true and unknown is unknown, false and unknown is false,
while unknown and unknown is unknown.

OR: The result of true or unknown is true, false or unknown is unknown, while unknown or unknown is unknown.

NOT: The result of not unknown is unknown
Kiren Siva
sumber
0

Jika Anda mencari ekspresi yang menghasilkan true untuk dua NULL, Anda dapat menggunakan:

SELECT 1 
WHERE EXISTS (
    SELECT NULL
    INTERSECT
    SELECT NULL
)

Akan sangat membantu jika Anda ingin mereplikasi data dari satu tabel ke tabel lainnya.

Piotr
sumber
0

Tes kesetaraan, misalnya, dalam pernyataan kasus ketika klausa, dapat diubah dari

XYZ = NULL 

untuk

XYZ IS NULL

Jika saya ingin memperlakukan string kosong dan kosong sama dengan NULL, saya sering juga menggunakan tes kesetaraan seperti:

(NULLIF(ltrim( XYZ ),'') IS NULL)
Allan F
sumber