Kerumitan Nilai Null dalam MySQL

PHPz
Lepaskan: 2024-07-17 09:48:49
asal
378 orang telah melayarinya

The Intricacies of Null Values in MySQL

pengenalan:

Bagi mereka yang baru menggunakan MySQL, termasuk saya sendiri, anda mungkin menemui hasil yang tidak dijangka apabila anda membuat pertanyaan daripada jadual yang mempunyai beberapa nilai nol. Dalam MySQL, null tidak benar atau palsu tetapi tidak diketahui, dan anda tidak boleh membandingkan null dengan null melainkan anda menggunakan operator 'IS NULL' atau 'IS NOT NULL'. Saya mendapati bahawa cara MySQL melayan null bukan sahaja menarik tetapi juga penting untuk difahami. Di sini, saya menunjukkan cara null berkelakuan menggunakan pelbagai fungsi MySQL!

Menyertai Jadual dengan Lajur Yang Mengandungi Nilai Null

NULL dengan INNER JOIN lwn. NULL dengan LEFT JOIN
Katakan terdapat dua jadual, seperti yang diterangkan di bawah:

Nama jadual : guru

id dept_id name
101 1 Shrivell
102 1 Throd
103 1 Splint
104 NULL Spiregrain
105 2 Cutflower
106 NULL Deadyawn

Nama jadual : jabatan

id name
1 Computing
2 Design
3 Engineering
NULL NULL

Perhatikan bahawa terdapat nilai nol dalam jadual guru. Apakah yang akan berlaku jika saya menggunakan INNER JOIN untuk menggabungkan kedua-dua jadual ini?

SELECT teachers.name, departments.name AS department
FROM teachers INNER JOIN departments
ON (teachers.dept_id = departments.id)

Salin selepas log masuk

Inilah hasilnya

+-----------+------------+
| Name      | Department |
+-----------+------------+
| Shrivell  | Computing  |
| Throd     | Computing  |
| Splint    | Computing  |
| Cutflower | Design     |
+-----------+------------+
Salin selepas log masuk

Perhatikan bahawa dalam keputusan, anda tidak melihat nama dua guru yang jabatan_idnya adalah batal.

Tetapi bagaimana pula dengan menggunakan LEFT JOIN? Jom kita tengok.
Berikut ialah pertanyaan di mana saya hanya menukar 'DALAM' dengan 'KIRI'.

SELECT teachers.name, departments.name AS department
FROM teachers LEFT JOIN departments
ON (teachers.dept_id = departments.id)

Salin selepas log masuk

Inilah hasilnya

+------------+------------+
| Name       | Department |
+------------+------------+
| Shrivell   | Computing  |
| Throd      | Computing  |
| Splint     | Computing  |
| Spiregrain | NULL       |
| Cutflower  | Design     |
| Deadyawn   | NULL       |
+------------+------------+
Salin selepas log masuk

Anda akan perasan bahawa semua guru disenaraikan. INNER JOIN tidak mengembalikan rekod dengan nilai nol, tetapi LEFT JOIN akan mengembalikannya.

KENAPA?

Perlu diingat bahawa apabila menggunakan operator kesamaan (=) dengan NULL ke NULL, hasilnya tidak benar atau palsu—ia tidak diketahui. Oleh itu, rekod dengan nilai NULL pada kedua-dua belah perbandingan tidak disertakan dalam set hasil apabila menggunakan INNER JOIN. Walau bagaimanapun, dengan sifat LEFT JOIN, ia memilih SEMUA rekod dari jadual sebelah kiri (iaitu jadual guru dalam kes ini), walaupun dept_id adalah batal. Tidak seperti INNER JOIN, yang akan mengalih keluar rekod sedemikian daripada senarai, LEFT JOIN mengekalkannya.

WUJUD & NULL dan IN & NULL

Kedua-dua EXISTS dan IN tidak mengembalikan rekod dengan nilai nol.
Mari kita pertimbangkan contoh di mana saya mempunyai jadual ini.

Nama jadual: pelanggan

customer_id first_name last_name phone_number
1 John Doe 123-456-7890
2 Jane Smith 987-654-3210
3 Alice Johnson NULL
4 Bob Brown 555-555-5555

Nama jadual: pelanggan_2

customer_id first_name last_name phone_number
1 John Doe 123-456-7890
2 Jane Smith NULL
3 Alice Johnson 111-222-3333
4 Bob Brown NULL

Here is a query:
Using EXISTS to check if a name in b_table exists in a_table.

SELECT * FROM customers AS c1
WHERE EXISTS(
SELECT * FROM customers_2 AS c2
WHERE c1.first_name = c2.first_name 
AND c1.last_name = c2.last_name 
AND c1.phone_number = c2.phone_number); 
Salin selepas log masuk

Using IN to see if name in b_table is in a_table

SELECT *
FROM customers AS c1
WHERE (c1.first_name, c1.last_name, c1.phone_number) IN (
    SELECT c2.first_name, c2.last_name, c2.phone_number
    FROM customers_2 AS c2
);

Salin selepas log masuk

Both returns the same result

+-------------+------------+-----------+--------------+
| customer_id | first_name | last_name | phone_number |
+-------------+------------+-----------+--------------+
| 1           | John       | Doe       | 123-456-7890 |
+-------------+------------+-----------+--------------+
Salin selepas log masuk

Notice that records with null values are not returned.

WHY?
Because with EXISTS, you can't link columns that are null. For IN, it ignores null values as if they don't exist. Thus, both treat nulls in the same way: neither returns nulls.

** HOWEVER, it's not the same story with NOT EXISTS and NOT IN when dealing with NULL!**

Let's take a look.
I simply swapped EXISTS for NOT EXISTS.

SELECT * FROM customers AS c1
WHERE NOT EXISTS(
SELECT * FROM customers_2 AS c2
WHERE c1.first_name = c2.first_name 
AND c1.last_name = c2.last_name 
AND c1.phone_number = c2.phone_number);

Salin selepas log masuk

Here is the result

| customer_id | first_name | last_name | phone_number  |
|-------------|------------|-----------|---------------|
| 2           | Jane       | Smith     | 987-654-3210  |
| 3           | Alice      | Johnson   | [NULL]        |
| 4           | Bob        | Brown     | 555-555-5555  |
Salin selepas log masuk

Notice that it is returning records with null values. Both Jane and Bob's phone numbers in the customers_2 table are null, but since both phone numbers have values in the customers table, the returned values are not null.

How about using NOT IN?

SELECT *
FROM customers AS c1
WHERE (c1.first_name, c1.last_name, c1.phone_number) NOT IN (
    SELECT c2.first_name, c2.last_name, c2.phone_number
    FROM customers_2 AS c2
);

Salin selepas log masuk

Here is the result

+-------------+------------+-----------+--------------+
| customer_id | first_name | last_name | phone_number |
+-------------+------------+-----------+--------------+
Salin selepas log masuk

Nothing is returned!
Why does NOT EXISTS return null values but NOT IN does not? It's because they both treat null differently. NOT EXISTS is simply the opposite of EXISTS. It returns EVERYTHING that is not returned by EXISTS, including nulls.

However, NOT IN returns records that evaluate to TRUE, but in MySQL, null is neither TRUE nor FALSE—it is unknown.

Let's take a look at the record for Jane Smith with Id2.
When NOT IN is used, it compares:
Jane != Jane OR Smith != Smith OR 987-654-3210 != null.

Jane != Jane -> False
Smith != Smith -> False
987-654-3210 != null -> NULL
False or False or Null evaluates to NULL, so the record doesn't get returned!

Here's a little twist:
What if the first name in the customers table does not match the first name in the customers_2 table?

Let’s compare:
Jane Smith 987-654-3210 (from the customers table) and Jack Smith null (from the customers_2 table).

Here is the result

+-------------+------------+-----------+--------------+
| customer_id | first_name | last_name | phone_number |
+-------------+------------+-----------+--------------+
| 2           | Jack       | Smith     | 987-654-3210 |
Salin selepas log masuk

What? You see Jack! Doesn't NOT IN fail to evaluate null as either false or true, so the record shouldn't be returned?

Let's analyze it:

Jane != Jack -> True
Smith != Smith -> False
987-654-3210 != null -> NULL

True or False or Null actually returns:
True || False -> True
True || NULL -> True
Therefore, the record gets returned!

If you want to understand how true, false, and null are evaluated, here is the link:

https://dev.mysql.com/doc/refman/8.0/en/logical-operators.html#operator_and

As you can see, it can get quite confusing when it comes to comparing null values.

At the end of the day, I think it's best to explicitly compare null values using IS NULL or IS NOT NULL, which returns true or false as shown below.

SELECT * FROM customers AS c1
WHERE EXISTS(
SELECT * FROM customers_2 AS c2
WHERE c1.first_name = c2.first_name 
AND c1.last_name = c2.last_name 
AND c1.phone_number = c2.phone_number OR  (c1.phone_number IS NULL AND c2.phone_number IS NULL));

Salin selepas log masuk

Conclusion

Handling null values in MySQL can be quite challenging, requiring careful attention when they are present in your database. It's crucial to conduct explicit null checking to clearly define how null values should be treated. By implementing the strategies I mentioned earlier, such as using IS NULL or IS NOT NULL, you can ensure more predictable and accurate query results.

Atas ialah kandungan terperinci Kerumitan Nilai Null dalam MySQL. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:dev.to
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan
Tentang kita Penafian Sitemap
Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!