12ก.ค.
NULL ใน SQL: กับดักที่คาดไม่ถึงในเงื่อนไข WHERE
sqlpostgresqldatabasenullwhereclausequery
14 ก.ค. 68 , 14:29
เคยสงสัยไหมว่าทำไมคิวรี่ != ถึงไม่ดึงข้อมูลแถวที่เป็น NULL ออกมา? บทความนี้จะอธิบายถึงพฤติกรรมของ NULL ใน SQL และวิธีเขียนเงื่อนไขเพื่อจัดการกับ "ค่าที่ไม่ทราบค่า" นี้อย่างถูกต้อง

หนึ่งในกับดักที่นักพัฒนา SQL ทั้งมือใหม่และมือเก๋าอาจเคยเจอ คือการที่ผลลัพธ์จากการคิวรี่ไม่เป็นไปตามที่คาดหวัง โดยเฉพาะเมื่อต้องจัดการกับคอลัมน์ที่มีค่า NULL

ลองจินตนาการถึงสถานการณ์นี้

เรามีตารางชื่อ orders ที่เก็บข้อมูลคำสั่งซื้อสินค้า และมีคอลัมน์ shipped_date เพื่อบอกวันที่สินค้าถูกจัดส่ง ถ้า shipped_date เป็น NULL แสดงว่าสินค้านั้นยังไม่ถูกจัดส่ง

ตาราง orders

order_id
product_name
customer_id
shipped_date
101
Keyboard
12
2025-07-10
102
Mouse
15
2025-07-11
103
Monitor
12
NULL
104
Webcam
21
2025-07-11
105
USB Hub
15
NULL

สมมติว่าเราต้องการหารายการสั่งซื้อทั้งหมดที่ ไม่ได้ถูกจัดส่งในวันที่ 2025-07-11 โดยเราอาจจะเขียนคิวรี่ง่ายๆ แบบนี้:

เราคาดหวังว่าจะได้ผลลัพธ์ 3 แถว คือ order_id 101 (ส่งวันอื่น), 103 (ยังไม่ส่ง) และ 105 (ยังไม่ส่ง) แต่ผลลัพธ์ที่ได้กลับมามีเพียงแถวเดียว:

order_id
product_name
shipped_date
101
Keyboard
2025-07-10

เกิดอะไรขึ้น? ทำไมรายการที่ยังไม่ถูกส่ง (shipped_date เป็น NULL) ถึงหายไป?

หัวใจของปัญหานี้คือความเข้าใจผิดเกี่ยวกับ NULL ในโลกของฐานข้อมูล NULL ไม่ใช่ค่าที่เท่ากับ 0, ไม่ใช่ช่องว่าง, และไม่ใช่ "ไม่มีอะไร" แต่มันคือ สถานะ (state) ที่บ่งบอกว่า "ไม่ทราบค่า" (unknown) หรือ "ไม่มีข้อมูล" (missing value)

ด้วยเหตุนี้ ระบบจัดการฐานข้อมูลจึงใช้ตรรกะแบบสามค่า (Three-Valued Logic หรือ 3VL) ซึ่งประกอบด้วย:

1.TRUE (จริง)
2.FALSE (เท็จ)
3.UNKNOWN (ไม่ทราบ)



เมื่อคุณนำ NULL ไปเปรียบเทียบกับค่าใดๆ ด้วยโอเปอเรเตอร์ทางตรรกะ (=, !=, <, >) ผลลัพธ์ที่ได้จะเป็น UNKNOWN เสมอ

NULL = '2025-07-11' → UNKNOWN
NULL != '2025-07-11' → UNKNOWN
NULL = NULL → UNKNOWN



เงื่อนไข WHERE ใน SQL จะดึงข้อมูลเฉพาะแถวที่ผลลัพธ์ของเงื่อนไขเป็น TRUE เท่านั้น มันจะทิ้งแถวที่ผลลัพธ์เป็น FALSE และ UNKNOWN ไปทั้งหมด นี่คือสาเหตุที่แถว order_id 103 และ 105 หายไปจากผลลัพธ์ของเรา



วิธีแก้ไข: จัดการ NULL อย่างชัดเจน

เพื่อให้ได้ผลลัพธ์ตามที่ต้องการ เราต้องเขียนเงื่อนไขเพื่อจัดการกับ NULL โดยเฉพาะ เป็นวิธีที่ตรงไปตรงมาที่สุด คือการเพิ่มเงื่อนไขเข้าไปว่า "หรือค่าในคอลัมน์นั้นต้องเป็น NULL"

ผลลัพธ์ที่ถูกต้อง:

order_id
product_name
shipped_date
101
Keyboard
2025-07-10
103
Monitor
NULL
105
USB Hub
NULL

ตอนนี้คิวรี่ทำงานถูกต้องแล้ว เพราะมันเลือกแถวที่ shipped_date ไม่ใช่วันที่ '2025-07-11' หรือ แถวที่ shipped_date เป็น NULL

วิธีที่ 2: ใช้ฟังก์ชัน COALESCE

COALESCE เป็นฟังก์ชันที่มีประโยชน์มากในการจัดการ NULL มันจะคืนค่าแรกที่ไม่ใช่ NULL จากรายการที่เราส่งเข้าไป เราสามารถใช้มันเพื่อแปลง NULL ให้เป็นค่าอื่นชั่วคราวเพื่อการเปรียบเทียบได้

ในคิวรี่นี้ ถ้า shipped_date เป็น NULL มันจะถูกแทนที่ด้วยวันที่ '1900-01-01' ก่อนนำไปเปรียบเทียบ ทำให้เงื่อนไข '1900-01-01' != '2025-07-11' เป็น TRUE และได้ผลลัพธ์ที่ถูกต้องเช่นกัน



การเปรียบเทียบกับ NULL เป็นหนึ่งในข้อผิดพลาดที่พบบ่อยที่สุดในการเขียน SQL จงจำไว้เสมอว่า NULL หมายถึง "ไม่ทราบค่า" และการเปรียบเทียบใดๆ กับมันจะให้ผลลัพธ์เป็น UNKNOWN เสมอ ดังนั้น หากต้องการจัดการกับแถวที่มีค่า NULL ในเงื่อนไข WHERE คุณต้องระบุอย่างชัดเจนโดยใช้ IS NULL หรือ IS NOT NULL เสมอครับ