พื้นฐานการพูดไม่มีอะไรผิดกับ NULL ในคีย์หลักแบบหลายคอลัมน์ แต่การมีสิ่งใดสิ่งหนึ่งมีความหมายว่าผู้ออกแบบไม่ได้ตั้งใจซึ่งเป็นเหตุผลว่าทำไมระบบจำนวนมากจึงเกิดข้อผิดพลาดเมื่อคุณลองทำสิ่งนี้
พิจารณากรณีของโมดูล / แพ็กเกจเวอร์ชันที่จัดเก็บเป็นชุดของฟิลด์:
CREATE TABLE module
(name varchar(20) PRIMARY KEY,
description text DEFAULT '' NOT NULL);
CREATE TABLE version
(module varchar(20) REFERENCES module,
major integer NOT NULL,
minor integer DEFAULT 0 NOT NULL,
patch integer DEFAULT 0 NOT NULL,
release integer DEFAULT 1 NOT NULL,
ext varchar(20),
notes text DEFAULT '' NOT NULL,
PRIMARY KEY (module, major, minor, patch, release, ext));
องค์ประกอบ 5 ประการแรกของคีย์หลักจะถูกกำหนดเป็นส่วนต่าง ๆ ของรุ่นวางจำหน่ายเป็นประจำ แต่แพคเกจบางตัวมีส่วนขยายที่กำหนดเองซึ่งโดยปกติจะไม่ใช่จำนวนเต็ม (เช่น "rc-foo" หรือ "vanilla" หรือ "เบต้า" หรืออะไรก็ตาม คนที่สี่สาขาไม่เพียงพออาจฝันถึง) หากแพ็กเกจไม่มีส่วนขยายแสดงว่าเป็น NULL ในโมเดลด้านบนและไม่มีอันตรายใด ๆ ที่จะเกิดขึ้นจากการปล่อยสิ่งต่าง ๆ
แต่สิ่งที่เป็นโมฆะ? มันควรจะแสดงถึงการขาดข้อมูลที่ไม่รู้จัก ที่กล่าวว่าอาจทำให้รู้สึกมากขึ้น:
CREATE TABLE version
(module varchar(20) REFERENCES module,
major integer NOT NULL,
minor integer DEFAULT 0 NOT NULL,
patch integer DEFAULT 0 NOT NULL,
release integer DEFAULT 1 NOT NULL,
ext varchar(20) DEFAULT '' NOT NULL,
notes text DEFAULT '' NOT NULL,
PRIMARY KEY (module, major, minor, patch, release, ext));
ในรุ่นนี้ส่วน "ext" ของ tuple ไม่ใช่ NULL แต่มีค่าเริ่มต้นเป็นสตริงว่าง - ซึ่งเป็น semantically (และในทางปฏิบัติ) แตกต่างจาก NULL NULL ไม่เป็นที่รู้จักในขณะที่สตริงว่างเป็นบันทึกโดยเจตนาของ "สิ่งที่ไม่มีอยู่" กล่าวอีกนัยหนึ่ง "ว่าง" และ "ว่าง" เป็นสิ่งที่แตกต่างกัน มันคือความแตกต่างระหว่าง "ฉันไม่มีคุณค่าที่นี่" และ "ฉันไม่รู้ว่าค่านี่คืออะไร"
เมื่อคุณลงทะเบียนแพ็กเกจที่ไม่มีส่วนขยายเวอร์ชันคุณรู้ว่ามันไม่มีส่วนขยายดังนั้นสตริงที่ว่างเปล่าจึงเป็นค่าที่ถูกต้อง ค่า NULL นั้นจะถูกต้องก็ต่อเมื่อคุณไม่รู้ว่ามันมีส่วนขยายหรือไม่หรือคุณรู้ว่ามันทำ แต่ไม่รู้ว่ามันเป็นอะไร สถานการณ์นี้ง่ายขึ้นที่จะจัดการกับระบบที่ค่าสตริงเป็นบรรทัดฐานเพราะไม่มีวิธีที่จะเป็นตัวแทนของ "จำนวนเต็มที่ว่างเปล่า" นอกเหนือจากการแทรก 0 หรือ 1 ซึ่งจะจบลงด้วยการเปรียบเทียบในภายหลัง (ซึ่งมี ผลกระทบของมันเอง) *
อนึ่งทั้งสองวิธีมีผลบังคับใช้ใน Postgres (เนื่องจากเรากำลังพูดถึง "enterprise" RDMBSs) แต่ผลลัพธ์การเปรียบเทียบอาจแตกต่างกันเล็กน้อยเมื่อคุณโยน NULL ลงในส่วนผสม - เนื่องจาก NULL == "ไม่รู้" ดังนั้นทั้งหมด ผลลัพธ์ของการเปรียบเทียบที่เกี่ยวข้องกับการยกเลิกค่า NULL เนื่องจากคุณไม่สามารถรู้สิ่งที่ไม่รู้จัก อันตราย! คิดอย่างรอบคอบเกี่ยวกับสิ่งนี้หมายความว่าผลการเปรียบเทียบค่า NULL เผยแพร่ผ่านชุดการเปรียบเทียบ นี่อาจเป็นแหล่งของข้อบกพร่องที่ละเอียดอ่อนเมื่อทำการเรียงลำดับการเปรียบเทียบและอื่น ๆ
Postgres ถือว่าคุณเป็นผู้ใหญ่และสามารถตัดสินใจได้ด้วยตัวเอง Oracle และ DB2 สมมติว่าคุณไม่ได้ตระหนักว่าคุณกำลังทำอะไรที่โง่และผิดพลาด นี่คือมักจะสิ่งที่ถูกต้อง แต่ไม่เสมอ - คุณอาจจะจริงไม่ทราบและมีความเป็นโมฆะในบางกรณีและดังนั้นจึงออกจากแถวที่มีองค์ประกอบที่ไม่รู้จักกับที่รถที่มีความหมายเป็นไปไม่ได้เป็นพฤติกรรมที่ถูกต้อง
ไม่ว่าในกรณีใดคุณควรพยายามกำจัดจำนวนของเขตข้อมูล NULL ที่คุณอนุญาตให้ใช้กับทั้งสคีมาและเพิ่มขึ้นเป็นสองเท่าดังนั้นเมื่อมาถึงเขตข้อมูลที่เป็นส่วนหนึ่งของคีย์หลัก ในกรณีส่วนใหญ่การปรากฏตัวของคอลัมน์ NULL เป็นตัวบ่งชี้ของการออกแบบ schema ที่ไม่เป็นมาตรฐาน (ซึ่งตรงกันข้ามกับการออกแบบ schema โดยเจตนา) และควรคิดอย่างหนักก่อนที่จะได้รับการยอมรับ
[* หมายเหตุ: มันเป็นไปได้ที่จะสร้างประเภทที่กำหนดเองนั่นคือการรวมกันของจำนวนเต็มและประเภท "ด้านล่าง" ที่จะหมายถึง "ว่างเปล่า" ซึ่งหมายถึง "ว่าง" ซึ่งตรงข้ามกับ "ไม่รู้จัก" น่าเสียดายที่นี่มีความซับซ้อนเล็กน้อยในการดำเนินการเปรียบเทียบและโดยปกติแล้วการพิมพ์ให้ถูกต้องนั้นไม่คุ้มกับความพยายามในการฝึกฝนเพราะคุณไม่ควรได้รับอนุญาตให้ใช้NULL
ค่าจำนวนมากตั้งแต่แรก ที่กล่าวว่ามันจะยอดเยี่ยมถ้า RDBMSs จะรวมBOTTOM
ประเภทเริ่มต้นนอกเหนือจากNULL
เพื่อป้องกันไม่ให้นิสัยของ conflating ความหมายของ "ไม่มีค่า" กับ "ค่าที่ไม่รู้จัก" โดยไม่ตั้งใจ ]