NULL ของ SQL นั้นแปลก
(jirevwe.github.io)-
ใน SQL ค่า NULL ถูกจัดการอย่างมีลักษณะเฉพาะ คอลัมน์ที่มีข้อจำกัด UNIQUE สามารถมีค่า NULL ได้หลายค่า
- เพราะค่า NULL แต่ละค่าถูกมองว่าเป็นค่าอิสระที่แตกต่างจาก NULL ตัวอื่น
- SQLite, Postgres และ MySQL ล้วนทำงานแบบเดียวกัน
-
การตั้งเกณฑ์
select '' = ''; -- Returns 1 (true) สตริงว่างเท่ากัน select 1 = 1; -- Returns 1 (true) ตัวเลขเท่ากัน select 1 = 0; -- Returns 0 (false) ตัวเลขไม่เท่ากัน select null = null; -- Returns NULL (null) อ้าว?- เนื่องจาก NULL เป็นตัวแทนของ "ค่าที่ไม่ทราบ" จึงถือว่าค่าที่ไม่ทราบสองค่านั้นไม่จำเป็นต้องเท่ากัน
- หากใช้ตัวดำเนินการ
ISจะสามารถตรวจสอบอัตลักษณ์ของ NULL ได้ เช่นnull is nullจะคืนค่า TRUE
-
เรื่องของความเป็นเอกลักษณ์
- เมื่อคอลัมน์ที่มีข้อจำกัด UNIQUE มีค่า NULL อยู่ ค่า NULL จะถือว่าแตกต่างกัน จึงไม่ละเมิดข้อจำกัดความเป็นเอกลักษณ์
- ตัวอย่างเช่น
('ray@mail.com', NULL)กับ('ray@mail.com', NULL)จะถูกมองว่าเป็นคนละแถว
-
ทำไม NULL ถึงถูกจัดการแบบนี้
- SQLite และฐานข้อมูล SQL-compatible อื่น ๆ ถูกออกแบบมาแบบนี้เพื่อให้จัดการ NULL ได้สอดคล้องกับฐานข้อมูลอื่น ๆ เอกสารมาตรฐาน SQL เสนอว่า NULL ควรมีความเป็นเอกลักษณ์ทุกที่ แต่ในทางปฏิบัติ SQL engine ส่วนใหญ่ไม่ได้จัดการ NULL แบบเป็นค่าเฉพาะใน SELECT DISTINCT หรือ UNION
-
วิธีรับประกันความเป็นเอกลักษณ์
-
ใช้ generated column
- สามารถบรรเทาปัญหาได้ด้วยการสร้างคอลัมน์ที่มีค่ากำหนดแน่นอนและไม่เป็น NULL เสมอ เช่น ใช้
COALESCE(deleted_at, '1970-01-01')เพื่อแทนค่า NULL - วิธีนี้อาจใช้พื้นที่เพิ่ม เพราะเป็นการเพิ่มฟิลด์เข้าไปในตาราง
- สามารถบรรเทาปัญหาได้ด้วยการสร้างคอลัมน์ที่มีค่ากำหนดแน่นอนและไม่เป็น NULL เสมอ เช่น ใช้
-
ใช้ partial index
- สามารถรับประกันความเป็นเอกลักษณ์ได้ด้วยการสร้าง partial index สำหรับ
emailเฉพาะกรณีที่deleted_atเป็น NULL - partial index ไม่ทำให้ตารางกว้างขึ้น ใช้พื้นที่น้อยกว่า และจะไม่เกิดข้อผิดพลาดเมื่อมีการลบเรคคอร์ดคู่เดิมซ้ำ ๆ
- สามารถรับประกันความเป็นเอกลักษณ์ได้ด้วยการสร้าง partial index สำหรับ
-
-
อัปเดต
- Oracle จัดการสตริงว่างเป็น NULL
-
สรุป
- แม้จะมองไม่เห็นเมื่อใช้ ORM แต่ลักษณะการจัดการ NULL อันเป็นเอกลักษณ์ของ SQL อาจทำให้สับสนได้ เอกสารมาตรฐาน SQL ไม่ได้เปิดเผยสาธารณะ และต้องจ่ายเงินจึงจะเข้าถึงได้
2 ความคิดเห็น
null ทุกแบบล้วนประหลาดทั้งนั้น
ดังนั้น null ของ SQL ที่จริง ๆ ก็ปกติดี เลยกลับดูเหมือนแปลกไปเสียอย่างนั้น…
ในดินแดนของคนตาเดียว คนสองตากลับกลายเป็นคนผิดปกติ…
ความเห็นจาก Hacker News
NULLใน SQL มีพื้นฐานมาจากตรรกะ TRUE-FALSE-UNKNOWN ของ Kleene ถ้าอ่านNULLเป็น UNKNOWN จะเข้าใจการดำเนินการหลายอย่างได้อย่างเป็นธรรมชาติมากขึ้นNULLเป็นตัวแทนที่ใช้สื่อถึง UNKNOWN และไม่อาจกล่าวได้ว่าNULLสองค่ามีค่าเท่ากันNULLS NOT DISTINCTเพื่อสร้าง unique index ได้ตอนที่แนวคิดเรื่อง
NULLถูกนำเข้ามาในทศวรรษ 1970 ก็คิดไว้แล้วว่าในอนาคตมันจะทำให้เกิดความสับสนมากมาย ผ่านมา 45 ปี ทุกวันนี้ก็ยังคงถกเถียงกันอยู่วิธีทำความเข้าใจ
NULLแบบตรงไปตรงมา: ค่าNULLในเซลล์หนึ่งของตารางคือวิธีแสดงว่า "ไม่มีค่า" เมื่อคุณต้องการค่าที่ไม่ซ้ำกัน กรณีที่ไม่มีค่าก็ไม่ควรถูกนำมาพิจารณาความกังขาต่อการใช้ ORM: ORM สะดวกก็จริง แต่ทำให้เกิดคนรุ่นหนึ่งที่ไม่เคยเรียนรู้ว่าฐานข้อมูลเชิงสัมพันธ์ทำงานจริงอย่างไร พฤติกรรมของ SQL
NULLสอดคล้องกับ relational algebra พื้นฐาน และNULLแบบสไตล์ C ต่างหากที่เป็นปัญหาทำให้นึกถึงมุกเกี่ยวกับการเปรียบเทียบ
NULLในบทสนทนาจากตอนหนึ่งของ Blackadderคิดว่าเป็นเรื่องแปลกที่ใน Oracle
NULLเท่ากับสตริงว่างในบริบทเชิงวัตถุ
nullมีประโยชน์ในการสื่อว่าแอตทริบิวต์หนึ่งไม่มีค่า ใน JavaScript มีทั้งnullและundefinedซึ่งอาจมองได้ว่าundefinedคือไม่รู้ค่า ส่วนnullคือไม่มีค่าNULLไม่ได้แปลกในแง่ของการไม่มีค่าซ้ำ เพราะNULLไม่เท่ากันเอง จึงไม่อาจถือเป็นค่าซ้ำได้ ถ้าไม่ชอบความหมายเชิงตรรกะของNULLก็สามารถใช้ sentinel value ได้SQL
NULLจะไม่ดูแปลกเลย หากพิจารณาว่าคุณต้องการให้ตรรกะเชิงสัมพันธ์ทำงานอย่างไรกับเรคอร์ดที่มีค่าซึ่งไม่มีอยู่จริง