อ่าน 19 นาที
ค่าว่าง (SQL)
ใน ภาษา SQL สำหรับการค้นหา ข้อมูลในฐานข้อมูล ค่าว่าง ( null หรือ NULL) เป็นเครื่องหมายพิเศษที่ใช้ระบุว่าค่าข้อมูลนั้นไม่มีอยู่ใน ฐานข้อมูล E. F.
ค่าว่าง (SQL)

ในภาษาSQL สำหรับการค้นหา ข้อมูลในฐานข้อมูล ค่าว่าง ( nullหรือNULL)เป็นเครื่องหมายพิเศษที่ใช้ระบุว่าค่าข้อมูลนั้นไม่มีอยู่ในฐานข้อมูล E. F. Coddผู้สร้างแบบจำลองฐานข้อมูลเชิงสัมพันธ์ ได้นำเสนอ ค่าว่างใน SQL เพื่อตอบสนองความต้องการที่ว่าระบบจัดการฐานข้อมูลเชิงสัมพันธ์ ( RDBMS ) ที่แท้จริงทั้งหมด ต้องรองรับการแสดง "ข้อมูลที่ขาดหายไปและข้อมูลที่ไม่สามารถใช้งานได้" Codd ยังได้แนะนำการใช้ สัญลักษณ์ โอเมก้า (ω) ตัวเล็กในภาษากรีกเพื่อแทนค่าว่างในทฤษฎีฐานข้อมูลใน SQL คำว่า "null" เป็นคำสงวนที่ใช้ระบุเครื่องหมายนี้ NULL
ค่าว่าง (null) ไม่ควรสับสนกับค่า0ค่าว่างบ่งชี้ถึงการไม่มีค่า ซึ่งไม่เหมือนกับค่าศูนย์ ตัวอย่างเช่น ในคำถาม "อดัมเป็นเจ้าของหนังสือจำนวนเท่าใด" คำตอบอาจเป็น "ศูนย์" ( ทราบว่าจำนวนหนังสือเป็นศูนย์ ) หรือ "ค่าว่าง" ( ไม่ทราบจำนวนหนังสือ) ในตารางฐานข้อมูลคอลัมน์ที่รายงานคำตอบนี้จะเริ่มต้นด้วยค่าว่าง (ทำเครื่องหมายด้วยค่าว่าง) และจะไม่ได้รับการอัปเดตด้วยค่าศูนย์จนกว่าจะแน่ใจว่าอดัมไม่มีหนังสือ
ใน SQL ค่า null เป็นเพียงตัวบ่งชี้ ไม่ใช่ค่าจริง การใช้งานแบบนี้แตกต่างจากภาษาโปรแกรมส่วนใหญ่ ซึ่งค่า nullของตัวอ้างอิงหมายความว่ามันไม่ได้ชี้ไปยังวัตถุ ใด ๆ
ประวัติศาสตร์
อีเอฟ คอดด์ กล่าวถึงค่าว่าง (null) เป็นวิธีการแสดงข้อมูลที่หายไปในแบบจำลองเชิงสัมพันธ์ในบทความปี 1975 ในวารสารFDT Bulletin of ACM - SIGMODบทความของคอดด์ที่ถูกอ้างถึงบ่อยที่สุดเกี่ยวกับความหมายของค่าว่าง (ตามที่นำมาใช้ใน SQL) คือบทความปี 1979 ในวารสารACM Transactions on Database Systemsซึ่งเขายังได้แนะนำแบบจำลองเชิงสัมพันธ์/แทสเมเนีย (Relational Model/Tasmania ) ด้วย แม้ว่าข้อเสนออื่นๆ จากบทความหลังนี้จะยังไม่เป็นที่รู้จักมากนักก็ตาม ส่วนที่ 2.3 ของบทความปี 1979 ของเขาได้อธิบายรายละเอียดเกี่ยวกับความหมายของการแพร่กระจายค่าว่างในการดำเนินการทางคณิตศาสตร์ รวมถึงการเปรียบเทียบโดยใช้ ตรรกะ แบบไตรภาค (สามค่า)เมื่อเปรียบเทียบกับค่าว่าง นอกจากนี้ยังอธิบายรายละเอียดเกี่ยวกับการจัดการค่าว่างในการดำเนินการเซตอื่นๆ (ประเด็นหลังนี้ยังคงเป็นที่ถกเถียงกันอยู่จนถึงทุกวันนี้) ใน แวดวง ทฤษฎีฐานข้อมูลข้อเสนอเดิมของคอดด์ (1975, 1979) ปัจจุบันเรียกว่า "ตารางคอดด์" (Codd tables) [ 1 ]ต่อมา Codd ได้เน้นย้ำข้อกำหนดที่ว่า RDBMS ทุกระบบต้องรองรับค่า Null เพื่อระบุข้อมูลที่หายไป ในบทความสองส่วนที่ตีพิมพ์ในนิตยสารComputerworld ในปี 1985 [ 2 ] [ 3 ]
มาตรฐาน SQL ปี 1986 โดยพื้นฐานแล้วได้นำข้อเสนอของ Codd มาใช้หลังจากต้นแบบการใช้งานในIBM System Rแม้ว่าDon Chamberlinจะยอมรับว่าค่าว่าง (รวมถึงแถวที่ซ้ำกัน) เป็นหนึ่งในคุณสมบัติที่ก่อให้เกิดข้อถกเถียงมากที่สุดของ SQL แต่เขาก็ปกป้องการออกแบบค่าว่างใน SQL โดยอ้างเหตุผลเชิงปฏิบัติว่ามันเป็นรูปแบบการสนับสนุนระบบที่ประหยัดที่สุดสำหรับข้อมูลที่ขาดหายไป ช่วยให้โปรแกรมเมอร์ไม่ต้องตรวจสอบซ้ำซ้อนในระดับแอปพลิเคชัน (ดูปัญหาเซมิเพรดิเคต ) ในขณะเดียวกันก็ให้ทางเลือกแก่นักออกแบบฐานข้อมูลที่จะไม่ใช้ค่าว่างหากต้องการ ตัวอย่างเช่น เพื่อหลีกเลี่ยงความผิดปกติที่รู้จักกันดี (กล่าวถึงในส่วนความหมายของบทความนี้) Chamberlin ยังโต้แย้งอีกว่า นอกเหนือจากการให้ฟังก์ชันการทำงานเกี่ยวกับค่าที่ขาดหายไปแล้ว ประสบการณ์จริงกับค่าว่างยังนำไปสู่คุณสมบัติภาษาอื่นๆ ที่อาศัยค่าว่าง เช่น โครงสร้างการจัดกลุ่มบางอย่างและการเชื่อมต่อภายนอก สุดท้าย เขาโต้แย้งว่าในทางปฏิบัติ Nulls ยังถูกใช้เป็นวิธีที่รวดเร็วในการแก้ไขสคีมา ที่มีอยู่ เมื่อจำเป็นต้องพัฒนาให้เกินกว่าเจตนาเดิม โดยไม่ได้เขียนโค้ดเพื่อชดเชยข้อมูลที่หายไป แต่เขียนโค้ดเพื่อชดเชยข้อมูลที่ไม่เกี่ยวข้อง ตัวอย่างเช่น ฐานข้อมูลที่ต้องการรองรับรถยนต์ไฟฟ้าอย่างรวดเร็วในขณะที่มีคอลัมน์ไมล์ต่อแกลลอน[ 4 ]
Codd ระบุในหนังสือของเขาในปี 1990 เรื่องThe Relational Model for Database Management, Version 2ว่าค่า Null เพียงค่าเดียวที่กำหนดโดยมาตรฐาน SQL นั้นไม่เพียงพอ และควรถูกแทนที่ด้วยตัวบ่งชี้ประเภท Null สองตัวแยกกันเพื่อระบุว่าเหตุใดข้อมูลจึงหายไป ในหนังสือของ Codd ตัวบ่งชี้ประเภท Null สองตัวนี้เรียกว่า 'A-Values' และ 'I-Values' ซึ่งแทน 'Missing But Applicable' และ 'Missing But Inapplicable' ตามลำดับ[ 5 ]คำแนะนำของ Codd จะต้องขยายระบบตรรกะของ SQL เพื่อรองรับระบบตรรกะสี่ค่า เนื่องจากความซับซ้อนเพิ่มเติมนี้ แนวคิดของค่า Null หลายค่าที่มีคำจำกัดความต่างกันจึงไม่ได้รับการยอมรับอย่างกว้างขวางในสาขาผู้ปฏิบัติงานด้านฐานข้อมูล อย่างไรก็ตาม ยังคงเป็นสาขาการวิจัยที่ดำเนินอยู่ โดยยังมีเอกสารจำนวนมากที่ยังคงตีพิมพ์อยู่
ความท้าทาย
ค่า Null เป็นจุดสนใจของข้อโต้แย้งและแหล่งที่มาของการถกเถียงเนื่องจากตรรกะสามค่า ที่เกี่ยวข้อง (3VL) ข้อกำหนดพิเศษสำหรับการใช้งานในSQL joinsและการจัดการพิเศษที่จำเป็นสำหรับฟังก์ชันการรวมและตัวดำเนินการจัดกลุ่ม SQL ศาสตราจารย์ด้านวิทยาศาสตร์คอมพิวเตอร์ Ron van der Meyden สรุปประเด็นต่างๆ ไว้ว่า: "ความไม่สอดคล้องกันในมาตรฐาน SQL หมายความว่าไม่สามารถกำหนดความหมายเชิงตรรกะที่เข้าใจง่ายใดๆ ให้กับการจัดการค่า Null ใน SQL ได้" [ 1 ]แม้ว่าจะมีการเสนอแนวทางแก้ไขปัญหาเหล่านี้หลายประการ แต่ความซับซ้อนของทางเลือกต่างๆ ทำให้ไม่สามารถนำไปใช้ได้อย่างแพร่หลาย
การแพร่กระจายศูนย์
การดำเนินการทางคณิตศาสตร์
เนื่องจาก Null ไม่ใช่ค่าข้อมูล แต่เป็นเครื่องหมายสำหรับค่าที่ไม่มีอยู่ การใช้ตัวดำเนินการทางคณิตศาสตร์กับ Null จะให้ผลลัพธ์ที่ไม่ทราบค่า ซึ่งแสดงด้วย Null [ 6 ]ในตัวอย่างต่อไปนี้ การคูณ 10 ด้วย Null จะได้ผลลัพธ์เป็น Null:
10 * NULL -- ผลลัพธ์คือ NULLสิ่งนี้อาจนำไปสู่ผลลัพธ์ที่ไม่คาดคิด ตัวอย่างเช่น เมื่อพยายามหารค่า Null ด้วยศูนย์ แพลตฟอร์มอาจส่งคืนค่า Null แทนที่จะโยน "ข้อยกเว้นข้อมูล - การหารด้วยศูนย์" ที่คาดไว้[ 6 ]แม้ว่าพฤติกรรมนี้จะไม่ได้กำหนดไว้ในมาตรฐาน ISO SQL แต่ผู้จำหน่าย DBMS หลายรายก็จัดการการดำเนินการนี้ในลักษณะเดียวกัน ตัวอย่างเช่น แพลตฟอร์ม Oracle, PostgreSQL, MySQL Server และ Microsoft SQL Server ต่างส่งคืนผลลัพธ์ Null สำหรับสิ่งต่อไปนี้:
NULL / 0การเชื่อมต่อสตริง
การดำเนินการ ต่อสตริงซึ่งเป็นเรื่องปกติใน SQL จะส่งผลลัพธ์เป็น Null เมื่อตัวถูกดำเนินการตัวใดตัวหนึ่งเป็น Null [ 7 ]ตัวอย่างต่อไปนี้แสดงให้เห็นผลลัพธ์ Null ที่ส่งคืนโดยใช้ Null กับ||ตัวดำเนินการต่อสตริงของ SQL
'ปลา' || NULL || 'มันฝรั่งทอด' -- ผลลัพธ์คือ NULLสิ่งนี้ไม่เป็นจริงสำหรับการใช้งานฐานข้อมูลทั้งหมด ตัวอย่างเช่น ใน Oracle RDBMS ค่า NULL และสตริงว่างถือว่าเป็นสิ่งเดียวกัน ดังนั้น 'Fish ' || NULL || 'Chips' จึงได้ผลลัพธ์เป็น 'Fish Chips' [ 8 ]
การเปรียบเทียบกับค่า NULL และตรรกะสามค่า (3VL)
เนื่องจาก Null ไม่ได้เป็นสมาชิกของโดเมนข้อมูล ใดๆ จึงไม่ถือว่าเป็น "ค่า" แต่เป็นเครื่องหมาย (หรือตัวยึดตำแหน่ง) ที่ระบุค่าที่ไม่กำหนดด้วยเหตุนี้ การเปรียบเทียบกับ Null จึงไม่สามารถให้ผลลัพธ์เป็น True หรือ False ได้ แต่จะให้ผลลัพธ์เชิงตรรกะที่สามเสมอ คือ Unknown [ 9 ]ผลลัพธ์เชิงตรรกะของนิพจน์ด้านล่าง ซึ่งเปรียบเทียบค่า 10 กับ Null คือ Unknown:
SELECT 10 = NULL -- ผลลัพธ์คือไม่ทราบค่าอย่างไรก็ตาม การดำเนินการบางอย่างกับค่า Null อาจส่งคืนค่าได้ หากค่าที่ไม่มีอยู่ไม่เกี่ยวข้องกับผลลัพธ์ของการดำเนินการนั้น พิจารณาตัวอย่างต่อไปนี้:
SELECT NULL OR TRUE -- ผลลัพธ์คือ Trueในกรณีนี้ ข้อเท็จจริงที่ว่าค่าทางด้านซ้ายของ OR นั้นไม่สามารถทราบได้นั้นไม่เกี่ยวข้อง เพราะผลลัพธ์ของการดำเนินการ OR จะเป็นจริงเสมอ ไม่ว่าค่าทางด้านซ้ายจะเป็นเท่าใดก็ตาม
SQL ใช้ผลลัพธ์เชิงตรรกะสามแบบ ดังนั้นการใช้งาน SQL จึงต้องรองรับตรรกะสามค่าเฉพาะ (3VL)กฎที่ควบคุมตรรกะสามค่าของ SQL แสดงอยู่ในตารางด้านล่าง ( pและqแทนสถานะเชิงตรรกะ) [ 10 ]ตารางความจริงที่ SQL ใช้สำหรับ AND, OR และ NOT สอดคล้องกับส่วนย่อยทั่วไปของตรรกะสามค่าของ Kleene และ Łukasiewicz (ซึ่งแตกต่างกันในคำจำกัดความของการบ่งชี้ อย่างไรก็ตาม SQL ไม่ได้กำหนดการดำเนินการดังกล่าว) [ 11 ]
| พี | q | พีหรือคิว | pและq | พี = คิว |
|---|---|---|---|---|
| จริง | จริง | จริง | จริง | จริง |
| จริง | เท็จ | จริง | เท็จ | เท็จ |
| จริง | ไม่ทราบ | จริง | ไม่ทราบ | ไม่ทราบ |
| เท็จ | จริง | จริง | เท็จ | เท็จ |
| เท็จ | เท็จ | เท็จ | เท็จ | จริง |
| เท็จ | ไม่ทราบ | ไม่ทราบ | เท็จ | ไม่ทราบ |
| ไม่ทราบ | จริง | จริง | ไม่ทราบ | ไม่ทราบ |
| ไม่ทราบ | เท็จ | ไม่ทราบ | เท็จ | ไม่ทราบ |
| ไม่ทราบ | ไม่ทราบ | ไม่ทราบ | ไม่ทราบ | ไม่ทราบ |
| พี | ไม่ใช่p |
|---|---|
| จริง | เท็จ |
| เท็จ | จริง |
| ไม่ทราบ | ไม่ทราบ |
ผลกระทบของค่าที่ไม่ทราบในเงื่อนไข WHERE
ตรรกะสามค่าของ SQL พบได้ในภาษาการจัดการข้อมูล (DML) ในเงื่อนไขการเปรียบเทียบของคำสั่ง DML และการสืบค้น ข้อความดังกล่าว ทำให้คำสั่ง DML ดำเนินการเฉพาะกับแถวที่เงื่อนไขประเมินค่าเป็นจริงเท่านั้น แถวที่เงื่อนไขประเมินค่าเป็น เท็จWHEREหรือไม่ทราบค่าจะไม่ถูกดำเนินการโดย คำสั่ง DML และจะถูกละทิ้งโดยการสืบค้น การตีความว่าไม่ทราบค่าและเท็จเป็นผลลัพธ์เชิงตรรกะเดียวกันเป็นข้อผิดพลาดทั่วไปที่พบเมื่อจัดการกับค่าว่าง[ 10 ]ตัวอย่างง่ายๆ ต่อไปนี้แสดงให้เห็นถึงความผิดพลาดนี้: INSERTUPDATEDELETESELECT
เลือก* จากt ที่i = NULL ;โดยหลักการแล้ว คำสั่ง SQL ตัวอย่างข้างต้นจะส่งคืนผลลัพธ์เป็นศูนย์แถวเสมอ เนื่องจากผลการเปรียบเทียบระหว่าง คอลัมน์ iกับค่า Null จะส่งคืนค่า Unknown เสมอ แม้แต่ในแถวที่iเป็น Null ก็ตาม ผลลัพธ์ Unknown นี้ทำให้SELECTคำสั่ง SQL ละทิ้งทุกแถวโดยสิ้นเชิง (อย่างไรก็ตาม ในทางปฏิบัติ เครื่องมือ SQL บางตัวจะดึงข้อมูลแถวโดยใช้การเปรียบเทียบกับค่า Null)
ตัวบ่งชี้การเปรียบเทียบเฉพาะค่าว่างและเฉพาะ 3VL
ตัวดำเนินการเปรียบเทียบ SQL พื้นฐานจะส่งคืนค่า Unknown เสมอเมื่อเปรียบเทียบสิ่งใดก็ตามกับค่า Null ดังนั้นมาตรฐาน SQL จึงจัดเตรียมเงื่อนไขการเปรียบเทียบเฉพาะสำหรับค่า Null สอง เงื่อนไข เงื่อนไข IS NULLand IS NOT NULL(ซึ่งใช้ ไวยากรณ์ postfix ) จะทดสอบว่าข้อมูลเป็นค่า Null หรือไม่[ 12 ]
มาตรฐาน SQL ประกอบด้วยคุณสมบัติเสริม F571 " การทดสอบ ค่าความจริง " ซึ่งแนะนำตัวดำเนินการเอกภาคเชิงตรรกะเพิ่มเติมอีกสามตัว (ที่จริงแล้วมีหกตัว หากนับรวมการปฏิเสธซึ่งเป็นส่วนหนึ่งของไวยากรณ์) โดยใช้สัญกรณ์โพสต์ฟิกเช่นกัน โดยมีตารางความจริงดังต่อไปนี้: [ 13 ]
| พี | p เป็นจริง | p ไม่เป็นความจริง | p เป็นเท็จ | p ไม่เป็นเท็จ | ค่า p ไม่ทราบค่า | p ไม่ใช่ค่าที่ไม่ทราบ |
|---|---|---|---|---|---|---|
| จริง | จริง | เท็จ | เท็จ | จริง | เท็จ | จริง |
| เท็จ | เท็จ | จริง | จริง | เท็จ | เท็จ | จริง |
| ไม่ทราบ | เท็จ | จริง | เท็จ | จริง | จริง | เท็จ |
คุณสมบัติ F571 นั้นเป็นอิสระจากการมีอยู่ของชนิดข้อมูลบูลีนใน SQL (ซึ่งจะกล่าวถึงในภายหลังในบทความนี้) และถึงแม้จะมีความคล้ายคลึงกันทางไวยากรณ์ แต่ F571 ก็ไม่ได้แนะนำตัวอักษรบูลีนหรือตัวอักษร สามค่า ในภาษา คุณสมบัติ F571 นั้นมีอยู่ในSQL92 [ 14 ] ก่อนที่ชนิดข้อมูลบูลีนจะถูกนำเข้าสู่มาตรฐานในปี 1999 เสียอีก อย่างไรก็ตาม ระบบจำนวนน้อยเท่านั้นที่ใช้งานคุณสมบัติ F571 โดย PostgreSQL เป็นหนึ่งในระบบเหล่านั้น
การเพิ่ม IS UNKNOWN ให้กับตัวดำเนินการอื่นๆ ของตรรกะสามค่าของ SQL ทำให้ตรรกะสามค่าของ SQL สมบูรณ์ในเชิงฟังก์ชัน [ 15 ] ซึ่งหมายความว่าตัวดำเนินการเชิงตรรกะสามารถแสดง (เมื่อรวมกัน) ฟังก์ชันเชิงตรรกะสามค่าใดๆ ที่เป็นไปได้
ในระบบที่ไม่รองรับคุณสมบัติ F571 สามารถจำลองการทำงานของ IS UNKNOWN p ได้ โดยการตรวจสอบทุกอาร์กิวเมนต์ที่อาจทำให้ค่าpเป็น Unknown และทดสอบอาร์กิวเมนต์เหล่านั้นด้วย IS NULL หรือฟังก์ชันเฉพาะสำหรับค่า NULL อื่นๆ แม้ว่าวิธีนี้อาจยุ่งยากกว่าก็ตาม
กฎของข้อยกเว้นที่สี่ (ในข้อความ WHERE)
ในตรรกะสามค่าของ SQL กฎของ ค่ากลางที่ถูกยกเว้น p หรือ NOT pจะไม่ประเมินค่าเป็นจริงสำหรับทุกpอีกต่อไป กล่าวคือ ในตรรกะสามค่าของ SQL ค่าpหรือ NOT pจะไม่ทราบค่าก็ต่อเมื่อpไม่ทราบค่า และจะเป็นจริงในกรณีอื่น ๆ เนื่องจากผลการเปรียบเทียบโดยตรงกับค่า Null ทำให้ได้ค่าตรรกะที่ไม่ทราบค่า ดังนั้นคำสั่ง SQL ต่อไปนี้จึงไม่ถูกต้อง
เลือก* จากstuff ที่( x = 10 ) หรือไม่( x = 10 );ไม่เทียบเท่าใน SQL กับ
เลือก* จากstuff ;ถ้าคอลัมน์ x มีค่า Null อยู่ ในกรณีนั้น คำสั่งค้นหาที่สองจะส่งคืนบางแถวที่คำสั่งค้นหาแรกไม่ส่งคืน กล่าวคือ แถวทั้งหมดที่ x เป็น Null ในตรรกะสองค่าแบบคลาสสิก กฎของค่ากลางที่ถูกยกเว้นจะช่วยให้สามารถลดความซับซ้อนของเงื่อนไข WHERE ได้ หรืออาจถึงขั้นตัดทิ้งไปเลยก็ได้ การพยายามนำกฎของค่ากลางที่ถูกยกเว้นมาใช้กับ 3VL ของ SQL นั้นเป็นการแบ่งแยกที่ผิดพลาด อย่างแท้จริง คำสั่งค้นหาที่สองนั้นเทียบเท่ากับ:
SELECT * FROM stuff ; -- (เนื่องจาก 3VL) เทียบเท่ากับ: SELECT * FROM stuff WHERE ( x = 10 ) OR NOT ( x = 10 ) OR x IS NULL ;ดังนั้น เพื่อให้การลดรูปคำสั่งแรกใน SQL ถูกต้อง จำเป็นต้องส่งคืนแถวทั้งหมดที่ x ไม่เป็นค่าว่าง
เลือก* จากstuff ที่x ไม่เป็นค่าว่าง;จากที่กล่าวมาข้างต้น โปรดสังเกตว่าสำหรับเงื่อนไข WHERE ใน SQL สามารถเขียน สัจนิรันดร์ที่คล้ายกับกฎของสิ่งที่ไม่รวมอยู่ตรงกลางได้ โดยสมมติว่ามีตัวดำเนินการ IS UNKNOWN อยู่p OR (NOT p ) OR ( p IS UNKNOWN) จะเป็นจริงสำหรับทุก述語pในหมู่นักตรรกศาสตร์ สิ่งนี้เรียกว่ากฎของสิ่งที่ไม่รวมอยู่ลำดับที่สี่
มีนิพจน์ SQL บางอย่างที่ไม่ชัดเจนว่าจุดที่เกิดภาวะกลืนไม่เข้าคายไม่ออกนั้นอยู่ที่ใด ตัวอย่างเช่น:
SELECT 'ok' WHERE 1 NOT IN ( SELECT CAST ( NULL AS INTEGER )) UNION SELECT 'ok' WHERE 1 IN ( SELECT CAST ( NULL AS INTEGER ));ไม่สร้างแถวใดๆ เนื่องจากINเป็นการแปลงเป็นเวอร์ชันแบบวนซ้ำของความเท่าเทียมกันเหนือชุดอาร์กิวเมนต์ และ 1<>NULL คือค่าที่ไม่รู้จัก เช่นเดียวกับ 1=NULL คือค่าที่ไม่รู้จัก (คำสั่ง CAST ในตัวอย่างนี้จำเป็นเฉพาะในบางการใช้งาน SQL เช่น PostgreSQL ซึ่งหากไม่ใช้คำสั่งนี้จะปฏิเสธด้วยข้อผิดพลาดในการตรวจสอบประเภท ในหลายระบบ การใช้ SELECT NULL ธรรมดาในซับควอรีก็เพียงพอแล้ว) กรณีที่ขาดหายไปข้างต้นคือ:
SELECT 'ok' WHERE ( 1 IN ( SELECT CAST ( NULL AS INTEGER ))) IS UNKNOWN ;ผลกระทบของค่าว่างและค่าที่ไม่ทราบในโครงสร้างอื่นๆ
เข้าร่วม
การเชื่อมต่อจะประเมินโดยใช้กฎการเปรียบเทียบเดียวกันกับที่ใช้สำหรับเงื่อนไข WHERE ดังนั้นจึงต้องระมัดระวังเมื่อใช้คอลัมน์ที่อนุญาตให้เป็นค่าว่างในเกณฑ์การเชื่อมต่อ SQL โดยเฉพาะอย่างยิ่ง ตารางที่มีค่าว่างจะไม่เท่ากับการเชื่อมต่อตัวเองตามธรรมชาติ ซึ่งหมายความว่าในขณะที่เป็นจริงสำหรับความสัมพันธ์R ใดๆ ในพีชคณิตเชิงสัมพันธ์การเชื่อมต่อตัวเองของ SQL จะไม่รวมแถวทั้งหมดที่มีค่าว่างที่ใดก็ได้[ 16 ]ตัวอย่างของพฤติกรรมนี้แสดงอยู่ในส่วนที่วิเคราะห์ความหมายของค่าที่หายไปของค่าว่าง
COALESCEฟังก์ชันหรือ นิพจน์ SQL CASEสามารถใช้เพื่อ "จำลอง" ความเท่าเทียมกันของค่า Null ในเกณฑ์การเชื่อมต่อได้ และ สามารถใช้เงื่อนไข ` IS NULLand` IS NOT NULLในเกณฑ์การเชื่อมต่อได้เช่นกัน เงื่อนไขต่อไปนี้จะทดสอบความเท่าเทียมกันของค่า A และ B และถือว่าค่า Null เท่ากัน
( A = B ) หรือ( A เป็นค่าว่างและB เป็นค่าว่าง)นิพจน์ CASE
SQL มีเงื่อนไขอยู่สองแบบ แบบแรกเรียกว่า "CASE แบบง่าย" ซึ่งทำงานเหมือนคำสั่ง switchส่วนอีกแบบเรียกว่า "CASE แบบค้นหา" ในมาตรฐาน และทำงานเหมือนคำสั่งif... elseif
นิพจน์ แบบง่ายCASEใช้การเปรียบเทียบความเท่าเทียมกันโดยปริยาย ซึ่งทำงานภายใต้กฎเดียวกันกับWHEREกฎของข้อกำหนด DML สำหรับค่า Null ดังนั้นนิพจน์แบบง่ายCASE จึง ไม่สามารถตรวจสอบการมีอยู่ของค่า Null ได้โดยตรง การตรวจสอบค่า Null ในCASEนิพจน์แบบง่ายจะให้ผลลัพธ์เป็น Unknown เสมอ ดังตัวอย่างต่อไปนี้:
SELECT CASE i WHEN NULL THEN 'Is Null' -- ค่านี้จะไม่ถูกส่งคืนWHEN 0 THEN 'Is Zero' -- ค่านี้จะถูกส่งคืนเมื่อ i = 0 WHEN 1 THEN 'Is One' -- ค่านี้จะถูกส่งคืนเมื่อ i = 1 END FROM t ;เนื่องจากนิพจน์i = NULLจะประเมินค่าเป็น Unknown ไม่ว่าคอลัมน์iจะมีค่าอะไรก็ตาม (แม้ว่าจะมีค่า Null ก็ตาม) ดังนั้นจึง'Is Null'จะไม่มีการส่งคืน ค่าสตริงนั้น
ในทางกลับกันCASEนิพจน์ที่ "ค้นหา" สามารถใช้述语 (predicate) เช่น ` IS NULLand` IS NOT NULLในเงื่อนไขได้ ตัวอย่างต่อไปนี้แสดงวิธีการใช้CASEนิพจน์ที่ค้นหาเพื่อตรวจสอบค่าว่าง (Null) อย่างถูกต้อง:
SELECT CASE WHEN i IS NULL THEN 'Null Result' -- ค่านี้จะถูกส่งคืนเมื่อ i เป็น NULL WHEN i = 0 THEN 'Zero' -- ค่านี้จะถูกส่งคืนเมื่อ i = 0 WHEN i = 1 THEN 'One' -- ค่านี้จะถูกส่งคืนเมื่อ i = 1 END FROM t ;ในCASEนิพจน์ที่ค้นหา สตริง'Null Result'จะถูกส่งคืนสำหรับทุกแถวที่iเป็นค่าว่าง (Null)
ภาษา SQL ของ Oracle มีฟังก์ชันในตัวDECODEที่สามารถใช้แทนนิพจน์ CASE แบบธรรมดาได้ และถือว่าค่าว่างสองค่าเท่ากัน
SELECT DECODE ( i , NULL , 'ผลลัพธ์เป็นค่าว่าง' , 0 , 'ศูนย์' , 1 , 'หนึ่ง' ) FROM t ;สุดท้ายนี้ โครงสร้างทั้งหมดเหล่านี้จะคืนค่า NULL หากไม่พบการจับคู่ โดยมีELSE NULLเงื่อนไขค่า เริ่มต้นอยู่ด้วย
คำสั่ง IF ในส่วนขยายเชิงกระบวนการ
SQL/PSM (SQL Persistent Stored Modules) กำหนด ส่วนขยาย เชิงกระบวนการสำหรับ SQL เช่นIFคำสั่ง `remove` อย่างไรก็ตาม ผู้จำหน่าย SQL รายใหญ่ๆ มักจะรวมส่วนขยายเชิงกระบวนการที่เป็นกรรมสิทธิ์ของตนเองไว้ด้วยเสมอ ส่วนขยายเชิงกระบวนการสำหรับการวนซ้ำและการเปรียบเทียบทำงานภายใต้กฎการเปรียบเทียบค่าว่าง (Null comparison rules) คล้ายกับที่ใช้สำหรับคำสั่ง DML และการสืบค้นข้อมูล ตัวอย่างโค้ดต่อไปนี้ในรูปแบบมาตรฐาน ISO SQL แสดงให้เห็นถึงการใช้ Null 3VL ในIFคำสั่ง `remove`
ถ้าi เป็นค่าว่างให้เลือก'ผลลัพธ์คือจริง' มิฉะนั้นถ้าi ไม่ใช่ค่าว่างให้เลือก'ผลลัพธ์คือเท็จ' มิฉะนั้นให้เลือก'ผลลัพธ์คือไม่ทราบ'คำสั่ง นี้IFจะดำเนินการเฉพาะกับการเปรียบเทียบที่ให้ผลลัพธ์เป็น True เท่านั้น สำหรับการเปรียบเทียบที่ให้ผลลัพธ์เป็น False หรือ Unknown IFคำสั่งจะส่งการควบคุมไปยังELSEIFส่วนถัดไป และสุดท้ายไปยังELSEส่วนสุดท้าย ผลลัพธ์ของโค้ดข้างต้นจะเป็นข้อความเสมอ'Result is Unknown'เนื่องจากผลการเปรียบเทียบกับค่า Null จะให้ผลลัพธ์เป็น Unknown เสมอ
การวิเคราะห์ความหมายของค่าว่าง (Null) ใน SQL
งานบุกเบิกของT. ImielińskiและW. Lipski Jr. (1984) [ 17 ]ได้วางกรอบในการประเมินความหมายที่ตั้งใจไว้ของข้อเสนอต่างๆ เพื่อนำความหมายค่าที่หายไปมาใช้ ซึ่งเรียกว่าพีชคณิต Imieliński-Lipskiส่วนนี้โดยคร่าวๆ จะตามบทที่ 19 ของตำรา "Alice" [ 18 ]การนำเสนอที่คล้ายกันปรากฏในบทวิจารณ์ของ Ron van der Meyden, §10.4 [ 1 ]
ในการคัดเลือกและการฉายภาพ: การแสดงผลที่อ่อนแอ
โครงสร้างที่ใช้แทนข้อมูลที่ขาดหายไป เช่น ตาราง Codd นั้น แท้จริงแล้วมีจุดประสงค์เพื่อใช้แทนชุดความสัมพันธ์ โดยแต่ละความสัมพันธ์จะใช้แทนค่าที่เป็นไปได้แต่ละค่าของพารามิเตอร์ ในกรณีของตาราง Codd นั้น หมายถึงการแทนที่ค่า Null ด้วยค่าที่เป็นรูปธรรม ตัวอย่างเช่น
| ชื่อ | อายุ |
|---|---|
| จอร์จ | 43 |
| แฮเรียต | NULL |
| ชาร์ลส์ | 56 |
| ชื่อ | อายุ |
|---|---|
| จอร์จ | 43 |
| แฮเรียต | 22 |
| ชาร์ลส์ | 56 |
| ชื่อ | อายุ |
|---|---|
| จอร์จ | 43 |
| แฮเรียต | 37 |
| ชาร์ลส์ | 56 |
โครงสร้าง (เช่น ตาราง Codd) จะถูกเรียกว่าเป็น ระบบ การแสดงข้อมูลที่ขาดหายไปอย่างเข้มแข็ง (strong representation system) หากคำตอบใดๆ ต่อการสอบถามที่ทำกับโครงสร้างนั้น สามารถระบุให้เฉพาะเจาะจงเพื่อให้ได้คำตอบสำหรับ การสอบถามที่สอดคล้องกัน ใดๆบนความสัมพันธ์ที่โครงสร้างนั้นแสดง ซึ่งถือเป็นแบบจำลองของโครงสร้างนั้น กล่าวให้แม่นยำยิ่งขึ้น หากqเป็นสูตรการสอบถามในพีชคณิตเชิงสัมพันธ์ (ของความสัมพันธ์ "บริสุทธิ์") และหากqคือการยกสูตรนั้นไปยังโครงสร้างที่ตั้งใจจะแสดงข้อมูลที่ขาดหายไป การแสดงข้อมูลที่เข้มแข็งจะมีคุณสมบัติว่า สำหรับการสอบถามq ใดๆ และโครงสร้าง (ตาราง) T ใดๆ qจะยก คำตอบ ทั้งหมดไปยังโครงสร้างนั้น กล่าวคือ:
(ข้อความข้างต้นต้องใช้ได้กับแบบสอบถามที่รับตารางจำนวนเท่าใดก็ได้เป็นอาร์กิวเมนต์ แต่การจำกัดไว้ที่ตารางเดียวก็เพียงพอสำหรับการอภิปรายในครั้งนี้) เห็นได้ชัดว่าตาราง Codd ไม่มีคุณสมบัติที่แข็งแกร่งนี้หากพิจารณาการเลือกและการฉายภาพเป็นส่วนหนึ่งของภาษาแบบสอบถาม ตัวอย่างเช่นคำตอบ ทั้งหมด สำหรับ
เลือกข้อมูลทั้งหมดจากตาราง Emp ที่อายุเท่ากับ22 ;ควรพิจารณาความเป็นไปได้ที่ความสัมพันธ์เช่น EmpH22 อาจมีอยู่ อย่างไรก็ตาม ตาราง Codd ไม่สามารถแสดงผลลัพธ์แบบ "ผลลัพธ์ที่มีแถวได้ 0 หรือ 1 แถว" ได้ แต่มีเครื่องมือที่เรียกว่าตารางเงื่อนไข (หรือ c-table) ซึ่งส่วนใหญ่มีประโยชน์ในเชิงทฤษฎีเท่านั้น ที่สามารถแสดงคำตอบดังกล่าวได้:
| ชื่อ | อายุ | เงื่อนไข |
|---|---|---|
| แฮเรียต | ω 1 | ω 1 = 22 |
โดยที่คอลัมน์เงื่อนไขจะถูกตีความว่าแถวนั้นไม่มีอยู่จริงหากเงื่อนไขเป็นเท็จ ปรากฏว่าเนื่องจากสูตรในคอลัมน์เงื่อนไขของตาราง c สามารถเป็น สูตร ตรรกะเชิงประพจน์ ใดๆ ก็ได้ ดังนั้นอัลกอริทึมสำหรับปัญหาที่ว่าตาราง c แสดงถึงความสัมพันธ์ที่เป็นรูปธรรมหรือไม่ จึงมี ความซับซ้อนในระดับ co-NP-completeและแทบไม่มีประโยชน์ในทางปฏิบัติ
ดังนั้น แนวคิดเรื่องการเป็นตัวแทนที่อ่อนกว่าจึงเป็นที่พึงปรารถนา อิมีลินสกีและลิปสกีได้นำเสนอแนวคิดเรื่องการเป็นตัวแทนที่อ่อน (weak representation ) ซึ่งโดยพื้นฐานแล้วอนุญาตให้การสอบถาม (ที่ยกขึ้น) เกี่ยวกับโครงสร้างส่งคืนการเป็นตัวแทนเฉพาะสำหรับ ข้อมูล ที่แน่นอนกล่าวคือ หากข้อมูลนั้นใช้ได้กับทุก กรณี ที่เป็นไปได้ใน "โลก " (โมเดล) ของโครงสร้างนั้น โดยเฉพาะอย่างยิ่ง โครงสร้างเป็นระบบการเป็นตัวแทนที่อ่อนหาก
ด้านขวามือของสมการข้างต้นคือ ข้อมูล ที่แน่นอน กล่าวคือ ข้อมูลที่สามารถดึงออกมาจากฐานข้อมูลได้อย่างแน่นอน โดยไม่คำนึงถึงค่าที่ใช้แทนค่าว่างในฐานข้อมูล ในตัวอย่างที่เราพิจารณาข้างต้น จะเห็นได้ง่ายว่าจุดตัดของแบบจำลองที่เป็นไปได้ทั้งหมด (กล่าวคือ ข้อมูลที่แน่นอน) ของการเลือกแบบสอบถามนั้นว่างเปล่า เนื่องจากตัวอย่างเช่น แบบสอบถาม (ที่ยังไม่ได้ยกขึ้น) จะไม่ส่งคืนแถวใด ๆ สำหรับความสัมพันธ์ EmpH37 โดยทั่วไปแล้ว Imielinski และ Lipski ได้แสดงให้เห็นว่าตาราง Codd เป็นระบบการแสดงผลที่อ่อนแอ หากภาษาแบบสอบถามถูกจำกัดไว้เฉพาะการฉายภาพ การเลือก (และการเปลี่ยนชื่อคอลัมน์) อย่างไรก็ตาม ทันทีที่เราเพิ่มการเชื่อมต่อหรือการรวมกันลงในภาษาแบบสอบถาม คุณสมบัติที่อ่อนแอนี้ก็จะหายไป ดังที่เห็นได้ในส่วนถัดไป WHEREAge=22
หากพิจารณาถึงการเข้าร่วมหรือสหภาพแรงงาน: แม้แต่การเป็นตัวแทนที่อ่อนแอ ก็ยังไม่เพียงพอ
พิจารณาคำสั่ง SQL ต่อไปนี้ที่ใช้กับตาราง Empในฐานข้อมูล Codd จากส่วนก่อนหน้า:
SELECT Name FROM Emp WHERE Age = 22 UNION SELECT Name FROM Emp WHERE Age <> 22 ;ไม่ว่าเราจะเลือกค่าNULLอายุของแฮเรียตเป็นค่าใดก็ตาม คำสั่งค้นหาข้างต้นจะส่งคืนคอลัมน์ชื่อทั้งหมดของโมเดลEmp ใดๆ ก็ตาม แต่เมื่อเรียกใช้คำสั่งค้นหา (ที่ยกมา) กับEmpเอง แฮเรียตจะหายไปเสมอ กล่าวคือ เราจะได้:
| ผลการค้นหาในEmp : |
| ผลการค้นหาในโมเดลEmp ใดๆ ก็ตาม : |
|
ดังนั้น เมื่อมีการเพิ่มคำสั่ง UNION เข้าไปในภาษาการสืบค้นข้อมูล ตาราง Codd จึงไม่ใช่แม้แต่ระบบการแสดงข้อมูลที่ขาดหายไปอย่างอ่อนแอ ซึ่งหมายความว่าการสืบค้นข้อมูลในตารางเหล่านั้นไม่ได้รายงาน ข้อมูล ที่แน่นอน ทั้งหมด ด้วยซ้ำ ความหมายของ UNION บนค่า Null ไม่ได้มีบทบาทในการสืบค้นนี้ ลักษณะ "การลืม" ของการสืบค้นย่อยทั้งสองนั้นเพียงพอที่จะรับประกันได้ว่าข้อมูลที่แน่นอนบางส่วนจะไม่ถูกรายงานเมื่อเรียกใช้การสืบค้นข้างต้นกับตาราง Emp ในตาราง Codd
สำหรับการเชื่อมต่อแบบธรรมชาติ (natural joins ) ตัวอย่างที่จำเป็นในการแสดงให้เห็นว่าข้อมูลบางอย่างอาจไม่ถูกรายงานโดยแบบสอบถามบางอย่างนั้นซับซ้อนกว่าเล็กน้อย ลองพิจารณาตารางต่อไปนี้
| เอฟ1 | เอฟ2 | เอฟ3 |
|---|---|---|
| 11 | NULL | 13 |
| 21 | NULL | 23 |
| 31 | 32 | 33 |
และการสอบถาม
SELECT F1 , F3 FROM ( SELECT F1 , F2 FROM J ) AS F12 NATURAL JOIN ( SELECT F2 , F3 FROM J ) AS F23 ;| ผลการค้นหาบน J: |
| ผลการค้นหาในโมเดลใดๆ ของ J: |
|
แนวคิดเบื้องหลังสิ่งที่เกิดขึ้นข้างต้นคือ ตาราง Codd ที่แสดงการฉายภาพในซับเควรีนั้นสูญเสียการติดตามข้อเท็จจริงที่ว่าค่า Null ในคอลัมน์ F12.F2 และ F23.F2 นั้นเป็นสำเนาของค่าเดิมในตาราง J ข้อสังเกตนี้ชี้ให้เห็นว่า การปรับปรุงตาราง Codd ที่ค่อนข้างง่าย (ซึ่งทำงานได้อย่างถูกต้องสำหรับตัวอย่างนี้) คือการใช้ค่าคงที่ Skolem (หมายถึงฟังก์ชัน Skolemซึ่งเป็นฟังก์ชันคงที่ เช่นกัน ) เช่น ω 12และ ω 22แทนที่จะใช้สัญลักษณ์ NULL เพียงตัวเดียว วิธีการดังกล่าวเรียกว่า v-tables หรือ Naive tables ซึ่งมีค่าใช้จ่ายในการคำนวณน้อยกว่า c-tables ที่กล่าวถึงข้างต้น อย่างไรก็ตาม มันยังไม่ใช่ทางออกที่สมบูรณ์สำหรับข้อมูลที่ไม่สมบูรณ์ในแง่ที่ว่า v-tables เป็นเพียงการแสดงผลที่อ่อนแอสำหรับเควรีที่ไม่ใช้การปฏิเสธใดๆ ในการเลือก (และไม่ใช้ความแตกต่างของเซตใดๆ ด้วย) ตัวอย่างแรกที่พิจารณาในส่วนนี้ใช้ข้อกำหนดการเลือกเชิงลบดังนั้นจึงเป็นตัวอย่างที่เควรี v-tables จะไม่รายงานข้อมูลที่แน่นอน WHEREAge<>22
ตรวจสอบข้อจำกัดและคีย์ต่างประเทศ
จุดหลักที่ตรรกะสามค่าของ SQL ตัดกับภาษาการกำหนดข้อมูล SQL (DDL) คือในรูปแบบของข้อจำกัดการตรวจสอบ ข้อจำกัดการตรวจสอบที่วางไว้บนคอลัมน์จะทำงานภายใต้ชุดกฎที่แตกต่างกันเล็กน้อยจากกฎสำหรับWHEREข้อความ DML ในขณะที่ข้อความ DML WHEREต้องประเมินค่าเป็น True สำหรับแถว ข้อจำกัดการตรวจสอบต้องไม่ประเมินค่าเป็น False (จากมุมมองเชิงตรรกะค่าที่กำหนดคือ True และ Unknown) ซึ่งหมายความว่าข้อจำกัดการตรวจสอบจะสำเร็จหากผลลัพธ์ของการตรวจสอบเป็น True หรือ Unknown ตารางตัวอย่างต่อไปนี้ที่มีข้อจำกัดการตรวจสอบจะห้ามไม่ให้แทรกค่าจำนวนเต็มใดๆ ลงในคอลัมน์iแต่จะอนุญาตให้แทรกค่า Null ได้ เนื่องจากผลลัพธ์ของการตรวจสอบจะประเมินค่าเป็น Unknown เสมอสำหรับค่า Null [ 19 ]
สร้างตารางt ( i ประเภทจำนวนเต็ม, ข้อจำกัดck_i ตรวจสอบ( i < 0 และi = 0 และi > 0 ) );เนื่องจากการเปลี่ยนแปลงค่าที่กำหนดไว้เมื่อเทียบกับ เงื่อนไข WHEREจากมุมมองทางตรรกะ กฎของค่ากลางที่ถูกยกเว้นจึงเป็นสัจนิรันดร์สำหรับข้อจำกัดCHECK ซึ่งหมายความว่า จะสำเร็จเสมอ ยิ่งไปกว่านั้น สมมติว่าค่า Null ถูกตีความว่าเป็นค่าที่มีอยู่แต่ไม่ทราบค่า ข้อจำกัด CHECK ที่ผิดปกติบางอย่าง เช่นตัวอย่างข้างต้น อนุญาตให้แทรกค่า Null ที่ไม่สามารถถูกแทนที่ด้วยค่าที่ไม่ใช่ Null ได้เลย CHECK (p OR NOT p)
เพื่อให้คอลัมน์ไม่ยอมรับค่าว่าง (Null) NOT NULLสามารถใช้ข้อจำกัดได้ดังตัวอย่างด้านล่างNOT NULLข้อจำกัดนี้มีความหมายเทียบเท่ากับข้อจำกัดตรวจสอบ (check constraint ) ที่มีIS NOT NULLเงื่อนไข (predicate)
สร้างตารางt ( i จำนวนเต็มไม่เป็นค่าว่าง);โดยค่าเริ่มต้น การตรวจสอบข้อจำกัดกับคีย์ต่างประเทศจะสำเร็จหากฟิลด์ใดฟิลด์หนึ่งในคีย์เหล่านั้นเป็นค่าว่าง (Null) ตัวอย่างเช่น ตาราง
สร้างตารางBooks ( title VARCHAR ( 100 ), author_last VARCHAR ( 20 ), author_first VARCHAR ( 20 ), FOREIGN KEY ( author_last , author_first ) REFERENCES Authors ( last_name , first_name ));จะอนุญาตให้แทรกแถวที่มี author_last หรือ author_first เป็นค่าว่างได้NULLโดยไม่คำนึงถึงวิธีการกำหนดตาราง Authors หรือสิ่งที่ตารางนั้นบรรจุอยู่ กล่าวคือ ค่าว่างในฟิลด์ใดฟิลด์หนึ่งจะอนุญาตให้มีค่าใดๆ ก็ได้ในอีกฟิลด์หนึ่ง แม้ว่าค่าดังกล่าวจะไม่พบในตาราง Authors ก็ตาม ตัวอย่างเช่น หากตาราง Authors มีเพียงค่าว่าง ค่าว่าง ('Doe', 'John')นั้น('Smith', NULL)จะตรงตามข้อจำกัดคีย์ต่างประเทศSQL-92ได้เพิ่มตัวเลือกพิเศษสองตัวสำหรับการจำกัดการจับคู่ในกรณีดังกล่าว หากMATCH PARTIALเพิ่มหลังจากREFERENCESประกาศแล้ว ค่าที่ไม่ใช่ค่าว่างใดๆ จะต้องตรงกับคีย์ต่างประเทศ เช่น ค่าว่าง('Doe', NULL)จะยังคงตรงกัน แต่ค่า('Smith', NULL)ว่างจะไม่ตรงกัน สุดท้าย หากMATCH FULLเพิ่มค่าว่าง ค่าว่างนั้น('Doe', NULL)จะไม่ตรงกับข้อจำกัดเช่นกัน แต่ค่าว่าง(NULL, NULL)จะยังคงตรงกันอยู่
ข้อต่อภายนอก

NULLแทนข้อมูลในผลลัพธ์ ผลลัพธ์ได้มาจากMicrosoft SQL Serverดังที่แสดงใน SQL Server Management Studioการเชื่อมตารางภายนอก (Outer Join)ใน SQL ซึ่งรวมถึงการเชื่อมตารางภายนอกด้านซ้าย (Left Outer Join), การเชื่อมตารางภายนอกด้านขวา (Right Outer Join) และการเชื่อมตารางภายนอกแบบเต็ม (Full Outer Join) จะสร้างค่า Null โดยอัตโนมัติเพื่อใช้เป็นค่าแทนข้อมูลที่หายไปในตารางที่เกี่ยวข้อง ตัวอย่างเช่น สำหรับการเชื่อมตารางภายนอกด้านซ้าย ค่า Null จะถูกสร้างขึ้นแทนที่แถวที่หายไปจากตารางที่ปรากฏทางด้านขวามือของLEFT OUTER JOINตัวดำเนินการ ตัวอย่างง่ายๆ ต่อไปนี้ใช้สองตารางเพื่อแสดงการสร้างค่า Null แทนข้อมูลในการเชื่อมตารางภายนอกด้านซ้าย
ตารางแรก ( Employee ) ประกอบด้วยหมายเลขประจำตัวพนักงานและชื่อ ในขณะที่ตารางที่สอง ( PhoneNumber ) ประกอบด้วยหมายเลขประจำตัวพนักงานและหมายเลขโทรศัพท์ ที่เกี่ยวข้อง ดังแสดงด้านล่าง
|
|
ตัวอย่างคำสั่ง SQL ต่อไปนี้เป็นการดำเนินการ Left Outer Join ระหว่างสองตารางนี้
SELECT e.ID , e.LastName , e.FirstName , pn.Number FROM Employee e LEFT OUTER JOIN PhoneNumber pn ON e.ID = pn.ID ;ชุดผลลัพธ์ที่ได้จากคำสั่ง SQL นี้แสดงให้เห็นว่า SQL ใช้ค่า Null เป็นตัวแทนสำหรับค่าที่หายไปจากตารางด้านขวา ( PhoneNumber ) ดังแสดงด้านล่าง
| รหัสประจำตัว | นามสกุล | ชื่อจริง | ตัวเลข |
|---|---|---|---|
| 1 | จอห์นสัน | โจ | 555-2323 |
| 2 | ลูอิส | แลร์รี่ | NULL |
| 3 | ทอมป์สัน | โทมัส | 555-9876 |
| 4 | แพตเตอร์สัน | แพทริเซีย | NULL |
ฟังก์ชันรวม
SQL กำหนดฟังก์ชันการรวมเพื่อลดความซับซ้อนของการคำนวณการรวมฝั่งเซิร์ฟเวอร์บนข้อมูล ยกเว้นCOUNT(*)ฟังก์ชัน ฟังก์ชันการรวมทั้งหมดจะดำเนินการขั้นตอนการกำจัดค่า Null เพื่อไม่ให้ค่า Null รวมอยู่ในผลลัพธ์สุดท้ายของการคำนวณ[ 20 ]
โปรดทราบว่าการกำจัดค่าว่าง (Null) ไม่ได้หมายความว่าเป็นการแทนที่ค่าว่างด้วยศูนย์ ตัวอย่างเช่น ในตารางต่อไปนี้AVG(i)(ค่าเฉลี่ยของค่าต่างๆi) จะให้ผลลัพธ์ที่แตกต่างจากAVG(j):
| ฉัน | เจ |
|---|---|
| 150 | 150 |
| 200 | 200 |
| 250 | 250 |
NULL | 0 |
นี่AVG(i)คือ 200 (ค่าเฉลี่ยของ 150, 200 และ 250) ในขณะที่AVG(j)คือ 150 (ค่าเฉลี่ยของ 150, 200, 250 และ 0) ผลข้างเคียงที่รู้จักกันดีของเรื่องนี้คือใน SQL นั้นAVG(z)ไม่เทียบเท่ากับSUM(z)/COUNT(*)แต่เทียบเท่าSUM(z)/COUNT(z)กับ[ 4 ]
ผลลัพธ์ของฟังก์ชันรวมอาจเป็นค่าว่าง (Null) ก็ได้ ตัวอย่างเช่น:
SELECT COUNT ( * ), MIN ( e . Wage ), MAX ( e . Wage ) FROM Employee e WHERE e . LastName LIKE '%Jones%' ;คำสั่ง SQL นี้จะแสดงผลลัพธ์เพียงหนึ่งแถวเสมอ โดยนับจำนวนพนักงานที่มีนามสกุล "Jones" และแสดงค่าจ้างต่ำสุดและสูงสุดที่พบสำหรับพนักงานเหล่านั้น อย่างไรก็ตาม หากไม่มีพนักงานคนใดตรงตามเกณฑ์ที่กำหนด จะเกิดอะไรขึ้น? การคำนวณค่าต่ำสุดหรือสูงสุดของชุดข้อมูลว่างเป็นไปไม่ได้ ดังนั้นผลลัพธ์จึงต้องเป็น NULL ซึ่งบ่งชี้ว่าไม่มีคำตอบ นี่ไม่ใช่ค่าที่ไม่ทราบ แต่เป็นค่า NULL ที่แสดงถึงการไม่มีค่า ผลลัพธ์จะเป็น:
| นับ(*) | ค่าจ้างขั้นต่ำ (e.Wage) | ค่าสูงสุด (e.Wage) |
|---|---|---|
| 0 | NULL | NULL |
เมื่อค่าว่างสองค่าเท่ากัน: การจัดกลุ่ม การเรียงลำดับ และการดำเนินการกับเซตบางอย่าง
เนื่องจากSQL:2003กำหนดให้เครื่องหมาย Null ทั้งหมดไม่เท่ากัน จึงจำเป็นต้องมีคำจำกัดความพิเศษเพื่อจัดกลุ่ม Null เข้าด้วยกันเมื่อดำเนินการบางอย่าง SQL กำหนด "ค่าสองค่าใดๆ ที่เท่ากัน หรือ Null สองค่าใดๆ" ว่า "ไม่แตกต่างกัน" [ 21 ] คำจำกัดความของ " ไม่แตกต่างกัน " นี้ทำให้ SQL สามารถจัดกลุ่มและเรียงลำดับ Null ได้เมื่อGROUP BYใช้ข้อความ (หรือคุณลักษณะภาษา SQL อื่นๆ ที่ทำการจัดกลุ่ม)
การดำเนินการ SQL อื่นๆ ข้อความ และคำหลักที่ใช้คำจำกัดความ "not distinct" ในการจัดการค่า Null ได้แก่:
- ข้อกำหนด
PARTITION BYของฟังก์ชันการจัดอันดับและการแบ่งหน้าต่าง เช่นROW_NUMBER - ตัว ดำเนินการ
UNION,INTERSECT, และEXCEPTซึ่งถือว่าค่า NULL เหมือนกันสำหรับการเปรียบเทียบ/การกำจัดแถว - คำ
DISTINCTหลักที่ใช้ในSELECTการค้นหา
หลักการที่ว่าค่า Null ไม่เท่ากัน (แต่ผลลัพธ์คือไม่ทราบ) ถูกละเมิดอย่างมีประสิทธิภาพในข้อกำหนด SQL สำหรับUNIONตัวดำเนินการ ซึ่งระบุค่า Null ว่าเท่ากัน[ 1 ]ด้วยเหตุนี้ การดำเนินการเซตบางอย่างใน SQL เช่น ยูเนียนและดิฟเฟอเรนซ์ อาจสร้างผลลัพธ์ที่ไม่แสดงข้อมูลที่แน่นอน ต่างจากการดำเนินการที่เกี่ยวข้องกับการเปรียบเทียบกับ NULL อย่างชัดเจน (เช่น การดำเนินการในWHEREข้อความที่กล่าวถึงข้างต้น) ในข้อเสนอของ Codd ในปี 1979 (ซึ่งได้รับการยอมรับโดย SQL92) ความไม่สอดคล้องกันทางความหมายนี้ได้รับการอธิบายโดยการโต้แย้งว่าการลบรายการซ้ำในการดำเนินการเซตเกิดขึ้น "ในระดับรายละเอียดที่ต่ำกว่าการทดสอบความเท่าเทียมกันในการประเมินการดำเนินการเรียกค้น" [ 11 ]
มาตรฐาน SQL ไม่ได้กำหนดลำดับการเรียงลำดับเริ่มต้นสำหรับค่า Null ไว้อย่างชัดเจน แต่ในระบบที่สอดคล้องกับมาตรฐาน ค่า Null สามารถเรียงลำดับก่อนหรือหลังค่าข้อมูลทั้งหมดได้โดยใช้ เงื่อนไข NULLS FIRSTor NULLS LASTของORDER BYรายการตามลำดับ อย่างไรก็ตาม ผู้จำหน่าย DBMS บางรายไม่ได้นำฟังก์ชันนี้ไปใช้ ผู้จำหน่ายที่ไม่ได้นำฟังก์ชันนี้ไปใช้อาจกำหนดวิธีการเรียงลำดับค่า Null ที่แตกต่างกันใน DBMS [ 19 ]
ผลกระทบต่อการดำเนินการดัชนี
ผลิตภัณฑ์ SQL บางตัวไม่สร้างดัชนีให้กับคีย์ที่มีค่า NULL ตัวอย่างเช่นPostgreSQLเวอร์ชันก่อน 8.3 ไม่สร้างดัชนีดังกล่าว โดยเอกสารประกอบสำหรับ ดัชนี B-treeระบุว่า[ 22 ]
โครงสร้างข้อมูลแบบ B-tree สามารถจัดการกับการค้นหาความเท่าเทียมกันและการค้นหาช่วงข้อมูลที่สามารถจัดเรียงตามลำดับได้ โดยเฉพาะอย่างยิ่ง ตัววางแผนการค้นหาของ PostgreSQL จะพิจารณาใช้ดัชนี B-tree เมื่อใดก็ตามที่คอลัมน์ที่มีดัชนีเกี่ยวข้องกับการเปรียบเทียบโดยใช้ตัวดำเนินการเหล่านี้: < ≤ = ≥ >
โครงสร้างที่เทียบเท่ากับการรวมกันของตัวดำเนินการเหล่านี้ เช่น BETWEEN และ IN สามารถนำไปใช้ได้โดยใช้การค้นหาดัชนีใน B-tree (แต่โปรดทราบว่า IS NULL ไม่เทียบเท่ากับ = และไม่สามารถใช้สร้างดัชนีได้)
ในกรณีที่ดัชนีบังคับใช้ความไม่ซ้ำกัน ค่า NULL จะถูกยกเว้นจากดัชนี และจะไม่บังคับใช้ความไม่ซ้ำกันระหว่างค่า NULL อีกครั้ง อ้างอิงจากเอกสาร PostgreSQL: [ 23 ]
เมื่อประกาศดัชนีเป็นค่าเฉพาะ (unique index) จะไม่อนุญาตให้มีหลายแถวในตารางที่มีค่าดัชนีเท่ากัน ค่าว่าง (null) จะไม่ถือว่าเท่ากัน ดัชนีเฉพาะแบบหลายคอลัมน์จะปฏิเสธเฉพาะกรณีที่คอลัมน์ที่ใช้สร้างดัชนีทั้งหมดเท่ากันในสองแถวเท่านั้น
นี่สอดคล้องกับพฤติกรรมที่กำหนดไว้ใน SQL:2003 สำหรับการเปรียบเทียบค่า Null แบบสเกลาร์
วิธีการจัดทำดัชนีค่า Null อีกวิธีหนึ่งเกี่ยวข้องกับการจัดการค่า Null โดยไม่แยกออกจากกันตามพฤติกรรมที่กำหนดไว้ใน SQL:2003 ตัวอย่างเช่น เอกสารประกอบ ของ Microsoft SQL Serverระบุไว้ดังนี้: [ 24 ]
สำหรับการจัดทำดัชนี ค่า NULL จะถือว่าเท่ากัน ดังนั้น จึงไม่สามารถสร้างดัชนีที่ไม่ซ้ำกัน หรือข้อจำกัดที่ไม่ซ้ำกันได้ หากคีย์เป็นค่า NULL มากกว่าหนึ่งแถว เลือกคอลัมน์ที่กำหนดเป็น NOT NULL เมื่อเลือกคอลัมน์สำหรับดัชนีที่ไม่ซ้ำกันหรือข้อจำกัดที่ไม่ซ้ำกัน
กลยุทธ์การสร้างดัชนีทั้งสองแบบนี้สอดคล้องกับพฤติกรรมของค่าว่าง (Null) ที่กำหนดไว้ในมาตรฐาน SQL:2003 เนื่องจากมาตรฐาน SQL:2003 ไม่ได้กำหนดวิธีการสร้างดัชนีไว้อย่างชัดเจน ดังนั้นกลยุทธ์การสร้างดัชนีสำหรับค่าว่างจึงขึ้นอยู่กับผู้จำหน่ายซอฟต์แวร์แต่ละรายที่จะออกแบบและนำไปใช้
ฟังก์ชันการจัดการค่าว่าง
SQL กำหนดฟังก์ชันสองฟังก์ชันเพื่อจัดการค่า Null อย่างชัดเจน ได้แก่NULLIFและCOALESCEฟังก์ชันทั้งสองเป็นตัวย่อของนิพจน์ที่ค้นหาCASE[ 25 ]
NULLIF
ฟังก์ชัน นี้NULLIFรับพารามิเตอร์สองตัว หากพารามิเตอร์ตัวแรกเท่ากับพารามิเตอร์ตัวที่สองNULLIFจะส่งคืนค่า Null มิฉะนั้น จะส่งคืนค่าของพารามิเตอร์ตัวแรก
NULLIF ( value1 , value2 )ดังนั้น จึงNULLIFเป็นคำย่อของCASEวลีต่อไปนี้:
กรณีเมื่อค่า 1 เท่ากับค่า 2 แล้วให้เป็นค่า NULL มิฉะนั้นให้เป็นค่า 1การรวมตัว
ฟังก์ชัน นี้COALESCEรับรายการพารามิเตอร์ และจะส่งคืนค่าที่ไม่ใช่ค่าว่าง (Null) ค่าแรกจากรายการนั้น:
COALESCE ( value1 , value2 , value3 , ... )COALESCECASEถูกกำหนดให้เป็นตัวย่อสำหรับ นิพจน์ SQL ต่อไปนี้ :
กรณีเมื่อค่า 1 ไม่เป็นค่าว่างให้กำหนดค่า 1 เมื่อค่า 2 ไม่เป็นค่าว่างให้กำหนดค่า 2 เมื่อค่า 3 ไม่เป็นค่าว่างให้กำหนดค่า 3 ... สิ้นสุดระบบจัดการฐานข้อมูล SQL บางระบบมีการใช้งานฟังก์ชันเฉพาะของผู้ผลิตที่คล้ายกับCOALESCEบางระบบ (เช่นTransact-SQL ) มีการใช้งานISNULLฟังก์ชัน หรือฟังก์ชันอื่นๆ ที่คล้ายคลึงกับCOALESCE(ดู รายละเอียด เพิ่มเติมเกี่ยวกับ ฟังก์ชันใน Transact-SQL ได้ที่ Isหัวข้อ ฟังก์ชันIS )
เอ็นวีแอล
ฟังก์ชัน Oracle นี้NVLรับพารามิเตอร์สองตัว โดยจะส่งคืนค่าพารามิเตอร์ตัวแรกที่ไม่ใช่ค่าว่าง หรือส่งคืนค่า NULL หากพารามิเตอร์ทั้งหมดเป็นค่าว่าง
COALESCEสามารถแปลงนิพจน์หนึ่ง ให้เป็น NVLนิพจน์ที่เทียบเท่ากันได้ดังนี้:
COALESCE ( val1 , ... , val { n } )เปลี่ยนเป็น:
NVL ( val1 , NVL ( val2 , NVL ( val3 , … , NVL ( val { n - 1 } , val { n } ) … )))ตัวอย่างการใช้งานของฟังก์ชันนี้คือการแทนที่ค่า NULL ในนิพจน์ด้วยค่าอื่น เช่น ในNVL(SALARY, 0)ตัวอย่างที่ระบุว่า 'ถ้าSALARYค่าเป็น NULL ให้แทนที่ด้วยค่า 0'
อย่างไรก็ตาม มีข้อยกเว้นที่สำคัญอยู่ประการหนึ่ง ในการใช้งานส่วนใหญ่ ฟังก์ชันCOALESCEจะประเมินพารามิเตอร์จนกว่าจะพบพารามิเตอร์ที่ไม่ใช่ค่าว่างตัวแรก ในขณะที่NVLฟังก์ชันอื่นจะประเมินพารามิเตอร์ทั้งหมด ซึ่งมีความสำคัญด้วยเหตุผลหลายประการ พารามิเตอร์หลังจากพารามิเตอร์ที่ไม่ใช่ค่าว่างตัวแรกอาจเป็นฟังก์ชัน ซึ่งอาจใช้ทรัพยากรการคำนวณมาก ไม่ถูกต้อง หรืออาจก่อให้เกิดผลข้างเคียงที่ไม่คาดคิดได้
การกำหนดประเภทข้อมูลเป็นค่าว่าง (Null) และค่าไม่ทราบ (Unknown)
ใน SQL ค่าNULLตัวอักษรไม่มีประเภท หมายความว่าไม่ได้กำหนดให้เป็นจำนวนเต็ม อักขระ หรือประเภทข้อมูล เฉพาะใดๆ [ 26 ]ด้วยเหตุนี้ บางครั้งจึงจำเป็น (หรือพึงประสงค์) ที่จะต้องแปลงค่า Null เป็นประเภทข้อมูลเฉพาะอย่างชัดเจน ตัวอย่างเช่น หากRDBMS รองรับฟังก์ชัน โอเวอร์โหลด SQL อาจไม่สามารถแก้ไขเป็นฟังก์ชันที่ถูกต้องได้โดยอัตโนมัติหากไม่ทราบประเภทข้อมูลของพารามิเตอร์ทั้งหมด รวมถึงพารามิเตอร์ที่ส่งค่า Null เข้ามาด้วย
การแปลงค่าจากNULLค่าคงที่ไปเป็นค่า Null ของชนิดข้อมูลเฉพาะ สามารถทำได้โดยใช้คุณสมบัติCASTที่แนะนำในSQL-92ตัวอย่างเช่น:
แปลงค่า( NULL เป็นจำนวนเต็ม)แสดงถึงค่าที่ไม่มีอยู่ของประเภท INTEGER
การกำหนดประเภทข้อมูลของ Unknown (แตกต่างจาก NULL หรือไม่) นั้นแตกต่างกันไปตามการใช้งาน SQL ในแต่ละระบบ ตัวอย่างเช่น ดังต่อไปนี้
เลือก'ok' โดยที่( NULL <> 1 ) เป็นค่าว่าง;โค้ดนี้ สามารถแยกวิเคราะห์และประมวลผลได้สำเร็จในบางสภาพแวดล้อม (เช่นSQLiteหรือPostgreSQL ) ซึ่งรวมค่าบูลีน NULL กับค่าที่ไม่ทราบ (Unknown) เข้าด้วยกัน แต่ไม่สามารถแยกวิเคราะห์ได้ในสภาพแวดล้อมอื่น (เช่นSQL Server Compact ) MySQLมีพฤติกรรมคล้ายกับPostgreSQLในเรื่องนี้ (โดยมีข้อแตกต่างเล็กน้อยคือMySQLถือว่า TRUE และ FALSE ไม่แตกต่างจากจำนวนเต็มทั่วไป 1 และ 0) นอกจากนี้ PostgreSQL ยังมีฟังก์ชันIS UNKNOWNตรวจสอบเงื่อนไข (predicate) ที่สามารถใช้ทดสอบว่าผลลัพธ์เชิงตรรกะสามค่าเป็นค่าที่ไม่ทราบ (Unknown) หรือไม่ แม้ว่าจะเป็นเพียงรูป แบบการเขียนโค้ดที่ช่วยให้เขียนได้ ง่ายขึ้นก็ตาม
ประเภทข้อมูลบูลีน
มาตรฐาน ISO SQL:1999ได้นำชนิดข้อมูล BOOLEAN มาใช้ใน SQL อย่างไรก็ตาม มันยังคงเป็นเพียงคุณสมบัติเสริมที่ไม่ใช่คุณสมบัติหลัก โดยมีรหัส T031 [ 27 ]
เมื่อถูกจำกัดด้วยNOT NULLข้อจำกัด BOOLEAN ใน SQL จะทำงานเหมือนกับชนิดข้อมูล Booleanจากภาษาอื่นๆ อย่างไรก็ตาม เมื่อไม่ถูกจำกัด ชนิดข้อมูล BOOLEAN แม้จะมีชื่อว่า BOOLEAN ก็สามารถเก็บค่าความจริง TRUE, FALSE และ UNKNOWN ได้ ซึ่งทั้งหมดนี้ถูกกำหนดให้เป็นค่า Boolean ตามมาตรฐาน มาตรฐานยังระบุด้วยว่า NULL และ UNKNOWN "สามารถใช้แทนกันได้เพื่อหมายถึงสิ่งเดียวกัน" [ 28 ] [ 29 ]
ประเภทบูลีนได้รับการวิพากษ์วิจารณ์ โดยเฉพาะอย่างยิ่งเนื่องจากพฤติกรรมที่กำหนดไว้ของตัวอักษร UNKNOWN ซึ่งจะไม่เท่ากับตัวเองเนื่องจากการระบุกับ NULL [ 30 ]
ดังที่กล่าวไว้ข้างต้น ใน การใช้งาน SQLของPostgreSQLนั้น Null ถูกใช้เพื่อแสดงผลลัพธ์ UNKNOWN ทั้งหมด รวมถึงค่า BOOLEAN UNKNOWN ด้วย PostgreSQL ไม่ได้ใช้งานค่า UNKNOWN แบบตัวอักษร (แม้ว่าจะใช้งานตัวดำเนินการ IS UNKNOWN ซึ่งเป็นคุณสมบัติเสริมก็ตาม) ผู้จำหน่ายรายใหญ่อื่นๆ ส่วนใหญ่ไม่รองรับประเภท Boolean (ตามที่กำหนดไว้ใน T031) ณ ปี 2012 [ 31 ] อย่างไรก็ตาม ส่วนขั้นตอนการทำงานของPL/SQL ของ Oracle รองรับตัวแปร BOOLEAN ซึ่งสามารถกำหนดค่าเป็น NULL ได้ และค่าจะถือว่าเหมือนกับ UNKNOWN [ 32 ]
ความขัดแย้ง
ข้อผิดพลาดที่พบบ่อย
ความเข้าใจผิดเกี่ยวกับวิธีการทำงานของค่า Null เป็นสาเหตุของข้อผิดพลาดจำนวนมากในโค้ด SQL ทั้งในคำสั่ง SQL มาตรฐาน ISO และในภาษา SQL เฉพาะที่รองรับโดยระบบจัดการฐานข้อมูลในโลกแห่งความเป็นจริง ข้อผิดพลาดเหล่านี้มักเกิดจากความสับสนระหว่างค่า Null กับ 0 (ศูนย์) หรือสตริงว่าง (ค่าสตริงที่มีความยาวเป็นศูนย์ ซึ่งแสดงใน SQL เป็น null '') อย่างไรก็ตาม มาตรฐาน SQL ได้กำหนดค่า Null ให้แตกต่างจากทั้งสตริงว่างและค่าตัวเลข0null ในขณะที่ค่า Null บ่งชี้ถึงการไม่มีค่าใดๆ สตริงว่างและค่าตัวเลขศูนย์ต่างก็แสดงถึงค่าจริง
ข้อผิดพลาดคลาสสิกอย่างหนึ่งคือการพยายามใช้ตัวดำเนินการเท่ากับ (=) =ร่วมกับคำหลักNULLเพื่อค้นหาแถวที่มีค่าว่าง (Null) ตามมาตรฐาน SQL แล้ว นี่เป็นไวยากรณ์ที่ไม่ถูกต้องและจะนำไปสู่ข้อความแสดงข้อผิดพลาดหรือข้อยกเว้น แต่การใช้งานส่วนใหญ่ยอมรับไวยากรณ์นี้และประเมินนิพจน์ดังกล่าวเป็นUNKNOWNเท็จ ผลที่ตามมาคือจะไม่พบแถวใด ๆ ไม่ว่าจะมีแถวที่มีค่าว่างหรือไม่ก็ตาม วิธีที่แนะนำในการค้นหาแถวที่มีค่าว่างคือการใช้述语 (predicate) IS NULLแทนการ= NULLใช้
SELECT * FROM sometable WHERE num = NULL ; -- ควรจะเป็น "WHERE num IS NULL"ในตัวอย่างที่เกี่ยวข้อง แต่ละเอียดอ่อนกว่านั้นWHEREข้อความหรือคำสั่งเงื่อนไขอาจเปรียบเทียบค่าของคอลัมน์กับค่าคงที่ มักเข้าใจผิดกันว่าค่าที่หายไปจะเป็น "น้อยกว่า" หรือ "ไม่เท่ากับ" ค่าคงที่หากฟิลด์นั้นมีค่าเป็น Null แต่ในความเป็นจริงแล้ว นิพจน์ดังกล่าวจะส่งคืนค่า Unknown ตัวอย่างอยู่ด้านล่าง:
SELECT * FROM sometable WHERE num <> 1 ; -- แถวที่ num เป็น NULL จะไม่ถูกส่งคืน-- ซึ่งขัดกับความคาดหวังของผู้ใช้หลายคนความสับสนเหล่านี้เกิดขึ้นเนื่องจากกฎแห่งเอกลักษณ์ถูกจำกัดในตรรกะของ SQL เมื่อจัดการกับการเปรียบเทียบความเท่าเทียมกันโดยใช้NULLตัวอักษรหรือUNKNOWNค่าความจริง SQL จะส่งคืนUNKNOWNผลลัพธ์ของนิพจน์เสมอ นี่คือความสัมพันธ์สมมูลบางส่วนและทำให้ SQL เป็นตัวอย่างของตรรกะที่ไม่สะท้อนกลับ[ 33 ]
ในทำนองเดียวกัน ค่า Null มักถูกเข้าใจผิดว่าเป็นสตริงว่าง ลองพิจารณาLENGTHฟังก์ชันที่ส่งคืนจำนวนอักขระในสตริง เมื่อส่งค่า Null เข้าไปในฟังก์ชันนี้ ฟังก์ชันจะส่งคืนค่า Null ซึ่งอาจนำไปสู่ผลลัพธ์ที่ไม่คาดคิดหากผู้ใช้ไม่คุ้นเคยกับตรรกะ 3 ค่า ตัวอย่างอยู่ด้านล่าง:
SELECT * FROM sometable WHERE LENGTH ( string ) < 20 ; -- แถวที่ string เป็น NULL จะไม่ถูกส่งคืนเรื่องนี้ยิ่งซับซ้อนขึ้นไปอีก เนื่องจากในโปรแกรมอินเทอร์เฟซฐานข้อมูลบางโปรแกรม (หรือแม้แต่การใช้งานฐานข้อมูลบางระบบ เช่น ของ Oracle) ค่า NULL จะถูกรายงานเป็นสตริงว่าง และสตริงว่างอาจถูกจัดเก็บอย่างไม่ถูกต้องเป็นค่า NULL
คำวิจารณ์
การใช้งานค่า Null ของ ISO SQL เป็นหัวข้อของการวิพากษ์วิจารณ์ การถกเถียง และการเรียกร้องให้เปลี่ยนแปลง ในThe Relational Model for Database Management: Version 2นั้น Codd แนะนำว่าการใช้งานค่า Null ของ SQL นั้นมีข้อบกพร่องและควรถูกแทนที่ด้วยตัวบ่งชี้ประเภท Null ที่แตกต่างกันสองตัว ตัวบ่งชี้ที่เขาเสนอจะหมายถึง"หายไปแต่ใช้ได้"และ"หายไปแต่ใช้ไม่ได้"ซึ่งรู้จักกันในชื่อค่า Aและค่า Iตามลำดับ หากข้อเสนอแนะของ Codd ได้รับการยอมรับ จะต้องมีการใช้งานตรรกะสี่ค่าใน SQL [ 5 ]คนอื่นๆ ได้แนะนำให้เพิ่มตัวบ่งชี้ประเภท Null เพิ่มเติมลงในข้อเสนอแนะของ Codd เพื่อระบุเหตุผลเพิ่มเติมที่ค่าข้อมูลอาจ "หายไป" ซึ่งจะเพิ่มความซับซ้อนของระบบตรรกะของ SQL ในช่วงเวลาต่างๆ ยังมีการเสนอให้ใช้ตัวบ่งชี้ Null ที่ผู้ใช้กำหนดเองหลายตัวใน SQL เนื่องจากความซับซ้อนของการจัดการค่า Null และระบบตรรกะที่จำเป็นในการรองรับตัวบ่งชี้ Null หลายตัว ข้อเสนอเหล่านี้จึงไม่ได้รับการยอมรับอย่างกว้างขวาง
Chris DateและHugh Darwenผู้เขียนThe Third Manifestoได้เสนอแนะว่าการใช้งานค่า Null ใน SQL นั้นมีข้อบกพร่องโดยเนื้อแท้และควรถูกกำจัดออกไปทั้งหมด[ 34 ]โดยชี้ให้เห็นถึงความไม่สอดคล้องกันและข้อบกพร่องในการใช้งานการจัดการค่า Null ใน SQL (โดยเฉพาะในฟังก์ชันรวม) เป็นหลักฐานว่าแนวคิดทั้งหมดของค่า Null นั้นมีข้อบกพร่องและควรถูกลบออกจากแบบจำลองเชิงสัมพันธ์[ 35 ]คนอื่นๆ เช่นFabian Pascal ผู้เขียน ได้ กล่าวถึงความเชื่อที่ว่า "วิธีการคำนวณฟังก์ชันควรจัดการกับค่าที่หายไปนั้นไม่ได้ถูกควบคุมโดยแบบจำลองเชิงสัมพันธ์"
สมมติฐานโลกปิด
อีกประเด็นหนึ่งที่ขัดแย้งเกี่ยวกับค่า Null คือ พวกมันละเมิด แบบจำลอง สมมติฐานโลกปิดของฐานข้อมูลเชิงสัมพันธ์โดยการนำสมมติฐานโลกเปิดเข้ามาใช้[ 36 ]สมมติฐานโลกปิด ในส่วนที่เกี่ยวข้องกับฐานข้อมูล ระบุว่า "ทุกสิ่งที่ระบุโดยฐานข้อมูล ไม่ว่าจะโดยชัดแจ้งหรือโดยปริยาย ล้วนเป็นความจริง ส่วนที่เหลือเป็นเท็จ" [ 37 ]มุมมองนี้ถือว่าความรู้เกี่ยวกับโลกที่จัดเก็บไว้ภายในฐานข้อมูลนั้นสมบูรณ์ อย่างไรก็ตาม ค่า Null ทำงานภายใต้สมมติฐานโลกเปิด ซึ่งบางรายการที่จัดเก็บในฐานข้อมูลถือว่าไม่ทราบ ทำให้ความรู้เกี่ยวกับโลกที่จัดเก็บไว้ของฐานข้อมูลไม่สมบูรณ์
ดูเพิ่มเติม
- คำสั่ง SQL
- ค่า NULL ใน: Wikibook SQL
- ตรรกะสามค่า
- ภาษาการจัดการข้อมูล
- กฎ 12 ข้อของค็อดด์
- ตรวจสอบข้อจำกัด
- แบบจำลองเชิงสัมพันธ์/แทสเมเนีย
- ระบบจัดการฐานข้อมูลเชิงสัมพันธ์
- การเชื่อมต่อ (SQL)
อ่านเพิ่มเติม
- EF Codd. ทำความเข้าใจความสัมพันธ์ (ตอนที่ 7). FDT Bulletin of ACM-SIGMOD, 7(3-4):23–28, 1975.
- Codd, EF (1979). "การขยายแบบจำลองเชิงสัมพันธ์ของฐานข้อมูลเพื่อจับความหมายได้มากขึ้น" ACM Transactions on Database Systems . 4 (4): 397– 434. CiteSeerX 10.1.1.508.5701 . doi : 10.1145/320107.320109 . S2CID 17517212 .โดยเฉพาะ §2.3.
- Date, CJ (2000). โมเดลฐานข้อมูลเชิงสัมพันธ์: การทบทวนและวิเคราะห์ย้อนหลัง: บันทึกทางประวัติศาสตร์และการประเมินผลงานของ EF Codd ในสาขาเทคโนโลยีฐานข้อมูล Addison Wesley Longman ISBN 978-0-201-61294-3.
- Klein, Hans-Joachim (1994). "วิธีการแก้ไขคำสั่ง SQL เพื่อรับประกันคำตอบที่แน่นอน" . ACM SIGMOD Record . 23 (3): 14– 20. doi : 10.1145/187436.187445 . S2CID 17354724 .
- Claude Rubinson, Nulls, Three-Valued Logic, and Ambiguity in SQL: Critiquing Date's Critique Archived 2016-03-05 at the Wayback Machine , SIGMOD Record, December 2007 (Vol. 36, No. 4)
- จอห์น แกรนท์, ค่าว่างใน SQL . SIGMOD Record, กันยายน 2008 (เล่มที่ 37, ฉบับที่ 3)
- Waraporn, Narongrit และ Kriengkrai Porkaew. " ความหมายที่เป็นค่าว่างสำหรับซับเควรีและเพรดิเคตอะตอมิก " IAENG International Journal of Computer Science 35.3 (2008): 305-313.
- Thalheim, Bernhard; Schewe, Klaus-Dieter (2011). "พีชคณิตและตรรกศาสตร์ 'ค่า' NULL" . Frontiers in Artificial Intelligence and Applications . 225 (Information Modelling and Knowledge Bases XXII). doi : 10.3233/978-1-60750-690-4-354 .
- Enrico Franconi และ Sergio Tessaris, เกี่ยวกับตรรกะของค่าว่างใน SQL , รายงานการประชุมเชิงปฏิบัติการนานาชาติ Alberto Mendelzon ครั้งที่ 6 ว่าด้วยพื้นฐานของการจัดการข้อมูล, Ouro Preto, บราซิล, 27–30 มิถุนายน 2012, หน้า 114–128
ลิงก์ภายนอก
- ข้อมูล Oracle NULL ถูกเก็บถาวรเมื่อวันที่ 12 เมษายน 2556 ที่Wayback Machine
- แถลงการณ์ฉบับที่สาม
- ผลกระทบของค่าว่าง (NULL) ต่อการจัดลำดับข้อมูล
- รายงานบั๊กของ Java เกี่ยวกับ JDBC ที่ไม่สามารถแยกแยะค่า null และสตริงว่างได้ ซึ่ง Sun ได้ปิดรายงานดังกล่าวโดยระบุว่า "ไม่ใช่บั๊ก"
สรุปเนื้อหา
ข้อมูลสำคัญจากบทความ
ข้อมูลสำคัญเกี่ยวกับ ค่าว่าง (SQL)
ใน ภาษา SQL สำหรับการค้นหา ข้อมูลในฐานข้อมูล ค่าว่าง ( null หรือ NULL) เป็นเครื่องหมายพิเศษที่ใช้ระบุว่าค่าข้อมูลนั้นไม่มีอยู่ใน ฐานข้อมูล E. F.
ประวัติศาสตร์
อีเอฟ คอดด์ กล่าวถึงค่าว่าง (null) เป็นวิธีการแสดงข้อมูลที่หายไปใน แบบจำลองเชิงสัมพันธ์ ในบทความปี 1975 ในวารสาร FDT Bulletin of ACM - SIGMOD บทความของคอดด์ที่ถูกอ้างถึงบ่อยที่สุดเกี่ยวกับความหมายของค่าว่าง (ตามที่นำมาใช้ใน SQL) คือบทความปี 1979 ในวารสาร ACM...
ความท้าทาย
ค่า Null เป็นจุดสนใจของข้อโต้แย้งและแหล่งที่มาของการถกเถียงเนื่องจาก ตรรกะสามค่า ที่เกี่ยวข้อง (3VL) ข้อกำหนดพิเศษสำหรับการใช้งานใน SQL joins และการจัดการพิเศษที่จำเป็นสำหรับฟังก์ชันการรวมและตัวดำเนินการจัดกลุ่ม SQL ศาสตราจารย์ด้านวิทยาศาสตร์คอมพิวเตอร์ Ron...
การดำเนินการทางคณิตศาสตร์
เนื่องจาก Null ไม่ใช่ค่าข้อมูล แต่เป็นเครื่องหมายสำหรับค่าที่ไม่มีอยู่ การใช้ตัวดำเนินการทางคณิตศาสตร์กับ Null จะให้ผลลัพธ์ที่ไม่ทราบค่า ซึ่งแสดงด้วย Null [ 6 ] ในตัวอย่างต่อไปนี้ การคูณ 10 ด้วย Null จะได้ผลลัพธ์เป็น Null: