Pertama sedikit teori:Null (SQL)
Bagian terpenting bagi kami dari tautan di atas:
Perbandingan dengan NULL dan logika tiga nilai (3VL)
Karena Null bukan anggota dari domain data apa pun, itu tidak dianggap sebagai "nilai", melainkan penanda (atau pengganti) yang menunjukkan tidak adanya nilai. Karena itu, perbandingan dengan Null tidak akan pernah menghasilkan Benar atau Salah, tetapi selalu dalam hasil logis ketiga,Tidak Diketahui.[8] Hasil logis dari ekspresi di bawah ini, yang membandingkan nilai 10 dengan Null, adalah Tidak Diketahui:
SELECT 10 = NULL -- Results in Unknown
sehingga perbandingan keduanya:x = NULL
dan x <> NULL
mengevaluasi ke NULL(tidak diketahui).
SQL mengimplementasikan tiga hasil logis, jadi implementasi SQL harus menyediakan logika tiga nilai khusus (3VL). Aturan yang mengatur logika tiga nilai SQL ditunjukkan pada tabel di bawah ini (p andq mewakili status logika)"[9] Tabel kebenaran yang digunakan SQL untuk AND, OR, dan NOT sesuai dengan fragmen umum dari logika tiga nilai Kleene dan ukasiewicz ( yang berbeda dalam definisi implikasinya, namun SQL tidak mendefinisikan operasi seperti itu).
+---------+-------------+-------------+-------------+-----------+--------+ | p | q | p OR q | p AND q | p = q |p != q | +---------+-------------+-------------+-------------+-----------+--------+ | True | True | True | True | True | False | | True | False | True | False | False | True | | True | Unknown | True | Unknown | Unknown | Unknown| | False | True | True | False | False | True | | False | False | False | False | True | False | | False | Unknown | Unknown | False | Unknown | Unknown| | Unknown | True | True | Unknown | Unknown | Unknown| | Unknown | False | Unknown | False | Unknown | Unknown| | Unknown | Unknown | Unknown | Unknown | Unknown | Unknown| +---------+-------------+-------------+-------------+-----------+--------+
Pengaruh Tidak Diketahui dalam klausa WHERE
Logika tiga nilai SQL ditemukan dalam Bahasa Manipulasi Data (DML) dalam perbandingan predikat pernyataan dan kueri DML. Klausa WHERE menyebabkan pernyataan DML bertindak hanya pada baris yang predikatnya bernilai True.
Jadi singkatnya:klausa WHERE memperlakukan NULL sebagai FALSE
Sekarang pertimbangkan kasus yang lebih sederhana:
SELECT * FROM T1;
| X |
|--------|
| 1 |
| (null) |
dan kueri:
SELECT * FROM t1 WHERE x IN (1, NULL);
Kueri di atas adalah singkatan dari yang ini:
SELECT * FROM t1
WHERE x = 1
OR x = NULL
Untuk baris kedua dari tabel t
( x =NULL) kondisi ini terlihat seperti:
WHERE NULL = 1
OR NULL = NULL
jadi kondisi ini untuk baris x=NULL
mengevaluasi ke NULL karena NULL=1
adalah NULL, NULL=NULL
adalah NULL, dan NULL OR NULL
juga NULL (silakan lihat tabel 3VL di atas).
Sekarang pertimbangkan kasus yang lebih aneh:
SELECT * FROM t1 WHERE x NOT IN (1, NULL);
Klausa ini x NOT IN (1, NULL)
setara dengan NOT ( x IN (1, NULL) )
jadi sama dengan:
NOT (
x = 1
OR
x = NULL
)
dan menurut hukum De Morgan setara dengan:
NOT ( x = 1 ) AND NOT ( x = NULL )
dan (jika kita mengganti NOT x = y
dengan x <> y
) itu juga setara dengan:
x <> 1 AND x <> NULL
Harap perhatikan baik-baik kondisi terakhir:
WHERE
x <> 1 AND x <> NULL
Kita tahu dari x <> NULL
selalu mengevaluasi ke NULL. Kita juga mengetahui dari tabel 3VL di atas, bahwa keduanya true AND NULL
adalah NULL dan false AND NULL
mengevaluasi ke FALSE, sehingga seluruh kondisi selalu mengevaluasi ke FALSE atau NULL, tetapi tidak pernah mengevaluasi ke TRUE.
Oleh karena itu kueri dengan kondisi ini:
SELECT .....
WHERE x NOT IN ( NULL, whatever)
selalu mengembalikan hasil yang kosong
Dan sekarang pertanyaan Anda, yang juga membuat penasaran:
SELECT * FROM t1
WHERE (id, val) NOT IN (select id, val from data2);
yang dapat ditulis ulang (menggunakan nilai konstan) menjadi:
SELECT * FROM t1
WHERE (id, val) NOT IN (
(1, null),
(2, 2 )
)
Kueri ini menggunakan apa yang disebut ekspresi nilai baris
Pada dasarnya suatu kondisi menggunakan ekspresi nilai baris seperti ini
(a, b) = (x, y)
setara dengan yang ini:
a = x AND b = y
jadi kueri di atas dapat ditulis ulang menjadi yang ini:
SELECT * FROM t1
WHERE NOT (
id = 1 AND val = NULL
OR
id = 2 AND val = 2
)
Menurut hukum De Morgan ini identik dengan:
SELECT * FROM t1
WHERE
NOT ( id = 1 AND val = NULL )
AND
NOT ( id = 2 AND val = 2 )
dan selanjutnya ke:
SELECT * FROM t1
WHERE
( id <> 1 OR val <> NULL )
AND
( id <> 2 OR val <> 2 )
Sejak bagian pertama ( id <> 1 OR val <> NULL )
dari kondisi bernilai benar hanya dalam kasus di mana id <> 1
(silakan lihat tabel 3VL di atas), kondisi ini dapat disederhanakan menjadi:
SELECT * FROM t1
WHERE
( id <> 1 )
AND
( id <> 2 OR val <> 2 )
dan selanjutnya (menurut hukum De Morgan) menjadi:
SELECT * FROM t1
WHERE
id <> 1 AND id <> 2
OR
id <> 1 AND val <> 2
jadi bukan (1,1)
atau (2,2)
dari sumber data1
mematuhi syarat-syarat tersebut.