เหตุผลที่ไม่ใช้หมายเลขที่ไม่มีค่าใน Oracle?


12

บริษัท ของเรากำลังติดต่อกับ บริษัท ซอฟต์แวร์อื่นสำหรับโครงการร่วมกันและเราได้รับแจ้งว่าหากไม่ควรแสดงค่าเฉพาะเราควรผ่านใน -5000 (ค่า Sentinel ตามอำเภอใจ) เหตุผลก็คือไม่มีคอลัมน์ตัวเลขในฐานข้อมูล Oracle ของพวกเขารองรับค่า Null ตามคำแนะนำของ Oracle Dev (ปัจจุบัน) ของพวกเขา บริษัท นี้ยังเขียนโค้ดส่วนใหญ่ของพวกเขาใน VB6 (ค่อยๆเปลี่ยนเป็น VB.NET ซึ่งเป็นอีกหัวข้อหนึ่งสำหรับอีกวันหนึ่ง ... ) จากความอยากรู้อย่างแท้จริงมีเหตุผลใดที่ถูกต้องสำหรับคำแนะนำนี้หรือไม่? ฉันไม่สามารถคิดถึงสิ่งใดในด้านของฉัน

--- แก้ไข

ขอบคุณสำหรับความคิดเห็นทั้งหมด ฉันโพสต์คำถามเดียวกันบน CodeProject.com ( ลิงก์ ) และได้รับคำติชมที่คล้ายกันมาก ดูเหมือนว่าจะมีเพียงครั้งเดียวที่เราจะสามารถพิสูจน์ได้ว่าการปฏิบัตินี้เกี่ยวข้องกับกุญแจต่างประเทศและฉันสามารถระบุได้ว่าไม่มีกุญแจต่างประเทศใด ๆ ในระบบ นักพัฒนาที่ทำตามข้อตกลงนี้ (ฉันเคยทำงานที่ บริษัท นั้น) มีประสบการณ์มากกว่าฉันอย่างมากดังนั้นฉันจึงต้องการตรวจสอบให้แน่ใจว่าไม่มีเหตุผลที่ถูกต้องสำหรับเรื่องนี้ก่อนที่จะทำการตรวจสอบ


2
คุณหมายถึงนอกเหนือจาก "นั่นคือสิ่งที่ API ของพวกเขาระบุ"?
Robert Harvey

ใช่ฉันอยากรู้ว่าทำไม API ของพวกเขาถึงระบุไว้ตั้งแต่แรก มีเหตุผลสำหรับการปฏิบัตินี้หรือเป็นเพียงความวิกลจริตบ้างไหม?

3
ความบ้าคลั่งของลำดับสูงสุด!
ฟิล

คำตอบ:


17

ความต้องการนั้นแนบเนียนมาก เช่นเดียวกับความคิดบ้าคลั่งที่ยอดเยี่ยมทั้งหมดอย่างไรก็ตามมันอาจขึ้นอยู่กับนักเก็ตที่มีความเป็นไปได้ที่จะนำไปสู่บริบทที่ห่างไกลจากผู้คนที่ไม่มีความเข้าใจในเหตุผลพื้นฐาน

มีความสมเหตุสมผลในการออกแบบคีมาฐานข้อมูลซึ่งไม่NULLอนุญาตให้ใช้ค่าใด ๆ อย่างไรก็ตามหากคุณทำเช่นนั้นคุณกำลังยืนยันถึงระดับของการทำให้เป็นมาตรฐานซึ่งองค์ประกอบที่ไม่จำเป็นทั้งหมดจะถูกแยกออกเป็นตารางแยกต่างหากพร้อมกับการอ้างอิงคีย์ต่างประเทศที่เหมาะสมกลับไปที่แม่ มันไม่ได้ทำบ่อย ๆ ในทางปฏิบัติ แต่ในกรณีที่มันสมเหตุสมผลที่จะทำมีประโยชน์

หากคุณกำลังจะออกแบบคีมาฐานข้อมูลซึ่งไม่NULLอนุญาตให้ใช้ค่าใด ๆ มันไม่สมเหตุสมผลที่จะอนุญาตให้เพียงอย่างเดียวจำเป็นต้องใช้ค่าเวทย์มนตร์เพื่อระบุว่ามีบางสิ่งที่ไม่รู้จัก ที่แนะนำปัญหาทั้งหมดที่อนุญาตให้NULLมีค่าบวกจะเพิ่มรหัสเพิ่มเติมเพื่อตรวจสอบค่าเวทย์มนตร์ที่จะต้องทำซ้ำทุกที่ มันไม่มีเหตุผลที่จะพัฒนา API ที่ต้องใช้ค่าเวทย์มนตร์ที่จะส่งผ่านโดยไม่คำนึงถึงการออกแบบฐานข้อมูล - ถ้าคุณจะโค๊ดรหัสของคุณด้วยการตรวจสอบค่าเวทย์มนตร์คุณไม่ควรปล่อยให้ความวิกลจริตแพร่กระจายไปยังระบบอื่น .


+1 และรหัสเพิ่มเติมเพื่อตรวจสอบค่าเวทย์มนตร์ไม่สามารถใช้ฟังก์ชั่นที่รู้จักกันดีCOALESCE()- ดังนั้นมันจึงมีความซับซ้อนยิ่งขึ้น
ypercubeᵀᴹ

และค่าจะต้องเก็บไว้ในดัชนีใด ๆ ในคอลัมน์นั้น ดัชนีไม่จำเป็นต้องเก็บค่าว่างไว้
Tripp Kinetics

15

ไม่มีเหตุผลที่ถูกต้องในการใช้ค่าเวทย์มนตร์แทนค่า NULL นี่อาจเป็นกระบวนการคิดของคนที่สร้างความยุ่งเหยิงนี้ พวกเขาเขียนอะไรเช่นนี้

 SELECT c1, c2 FROM t1 WHERE c3 < 30;

เมื่อสิ่งนี้ไม่ส่งคืนผลลัพธ์ที่พวกเขาคาดหวังพวกเขาตระหนักว่ามันไม่รวม NULL และจะต้องเขียนสิ่งนี้:

SELECT c1, c2 FROM t1 WHERE c3 < 30 OR c3 IS NULL;

พวกเขาไม่ต้องการเขียนหรือลืมในอนาคตที่จะเขียนสิ่งนี้ดังนั้นพวกเขาจึงคิดหาวิธีทำให้ NULLS -5000 ทั้งหมด ข้อความค้นหาดั้งเดิมของพวกเขาจัดการ NULL ได้อย่างน่าอัศจรรย์โดยไม่มีการเปลี่ยนแปลงใด ๆ สิ่งที่พวกเขาไม่ทราบก็คือตอนนี้คนที่ต้องการยกเว้นค่าเหล่านี้ต้องเขียนสิ่งนี้:

SELECT c1, c2 FROM t1 WHERE c3 < 30 AND c3 <> -5000;

หรือถ้าพวกเขาต้องการค่าเหล่านี้และกำลังค้นหาช่วงที่สูงขึ้น:

SELECT c1, c2 FROM t1 WHERE c3 > 40 OR c3 = -5000;

พวกเขาอาจไม่ทราบว่าสิ่งต่อไปนี้จะไม่มีความหมายอีกต่อไป:

SELECT c1, c2 FROM t1 WHERE c3 IS NULL;

แทนที่จะมีคนจำค่าเวทย์มนตร์ ด้วยประเภทข้อมูลแต่ละประเภทที่ใช้พวกเขาจะต้องจำค่าเวทมนตร์เพิ่มเติมเช่น 1/1 // 1900, "Z", -5000 นอกจากนี้เมื่อค่าเวทย์มนตร์อยู่ในข้อมูลพวกเขาจะต้องจำค่าเวทย์มนตร์อื่น

ดังนั้นสำหรับกรณีเฉพาะหนึ่ง ๆ ทำให้รหัสง่ายขึ้นโดยเสียค่าใช้จ่ายของกรณีอื่น ๆ ไม่ต้องพูดถึงพื้นที่ดิสก์ขนาดดัชนีการแยกวิเคราะห์แบบสอบถามความสอดคล้อง ฯลฯ


8

มันบ้าที่สุดและไม่มีเหตุผลสำหรับมัน NULLถูกสร้างขึ้นเพื่อแสดงถึงการไม่มีค่า & เพื่อใช้ค่าจริงเช่น -5000 คือ bonkers

โดยปกติฉันจะไม่เขียนคำตอบสั้น ๆ นี้ แต่คำถามที่ควรจะเป็นหนึ่งในสิ่งที่มองเห็นได้มากที่สุดใน dba.se และยิ่งคำตอบดีกว่า


5

ผมคิดเกี่ยวกับเรื่องนี้สำหรับบิตพยายามที่จะเป็นบวกและแสดงให้เห็นถึงความจำเป็นในการใช้ค่าที่พลแทนโมฆะและดูเหมือน (กับผมอย่างน้อย) จะไม่มีเหตุผลที่ถูกต้องนี้ยกเว้นบางทีในชุดข้อมูลการทำเหมืองข้อมูลปิด เพื่อปรับปรุงและลดความซับซ้อนของประสิทธิภาพและข้อความค้นหาจากนั้นเฉพาะในกรณีที่ตัวเลขไม่ใช่ค่าที่อาจบิดเบือนข้อมูล แม้แต่สิ่งนี้ก็จะต้องมีการพิจารณาอย่างรอบคอบ ในทุกสถานการณ์ในโลกแห่งความเป็นจริงที่ให้คุณค่ากับความว่างเปล่าไม่ใช่วิธีปฏิบัติที่ดี นี่จะเปลี่ยนคำจำกัดความคอลัมน์ไม่เป็นโมฆะจากเพื่อนของคุณไปเป็นศัตรูของคุณเพราะมันไม่เป็นความจริง

มันเป็นสิ่งที่แตกต่างกันมากที่จะบอกว่าแอปพลิเคชันของเราไม่ควรรับค่า NULL สำหรับคอลัมน์ (หรือแม้แต่ทั้งหมด) บางคอลัมน์ นี่เป็นวิธีปฏิบัติที่สมเหตุสมผลและมีประโยชน์และมีเอกสารที่เป็นประโยชน์ในการไม่อนุญาตให้มีค่า Null (ตัวอย่างเช่นคีย์และดัชนีและการคำนวณเชิงสถิติ) อย่างไรก็ตามการกำหนดค่าให้กับ "นั่งในสถานที่" ของค่า null นั้นไม่เหมือนกันทั้งหมด มันเป็นไม้เท้าสำหรับการย้อนกลับของคุณเองเนื่องจากคุณต้องเลือกค่าที่ไม่เคยใช้มาก่อนให้กรองค่านี้ตามที่คุณต้องการให้เป็นโมฆะและอย่าลืมใช้ในการคำนวณและสรุปและลบออกจากฟีดข้อมูลภายนอก . อย่างน้อยก็เลวร้ายกว่าการใช้ null เพื่อแทนค่าจริงซึ่งเป็นสิ่งที่คุณบอกตัวเองว่าคุณกำลังหลีกเลี่ยง แต่คุณไม่ได้

ปัญหาส่วนใหญ่ที่ทำให้เกิดโมฆะเมื่อเข้าใจสามารถจัดการ (ดัชนีปกติดีขึ้นฟังก์ชั่นหรือดัชนีบิตแมปหรือด้วยง่าย ๆ เมื่อ x ไม่เป็นโมฆะ) คุณคิดว่าที่ Telco ขนาดใหญ่หรือที่ Amazon ในการประชุมประสิทธิภาพรายเดือน DBA บางคนกำลังสรุปแผนที่ยอดเยี่ยมนี้เพื่อเร่งการสืบค้นบนชุดข้อมูลมหาศาลของพวกเขาสักหน่อย "โดยการแทนที่ null ด้วยค่าโดยพลการเช่น -5000 หรืออะไรก็ตาม - ฉันเปิดคุณค่า ... " หรือคุณคิดว่าพวกเขาใช้เวลาของพวกเขาแยกระหว่างการออกแบบโปรแกรมที่ดีที่จะกรองออก nulls ไม่พึงประสงค์และเพิ่มประสิทธิภาพการค้นหาบนพื้นฐานของข้อมูลที่เกิดขึ้นจริงที่พวกเขาได้รับจาก ? ตกลงดีบางทีการประชุมรายเดือนนั้นค่อนข้างมองในแง่ดี แต่เมื่อใดก็ตามที่เกิดขึ้นฉันสามารถรับรองได้ว่า "การแทนที่ค่าศูนย์ด้วย -5000 (หรืออะไรก็ตาม) สำหรับ API ที่ดีกว่า" ไม่ใช่รายการวาระ

สำหรับฉันมันเป็นเรื่องดีที่จะบอกว่าฉันจะไม่ยอมรับข้อมูลที่หายไป (คุณต้องมีอายุหรือราคาหรือรหัสภูมิภาคหรืออะไรก็ตาม) และบางครั้งก็ดีที่จะพูดสำหรับคอลัมน์นี้มีค่าเริ่มต้นที่จะป้อนถ้า คุณไม่ใส่อย่างอื่น ไม่ควรตั้งค่าให้เป็นโมฆะ คิดเกี่ยวกับฟิลด์ชื่อกลางเป็นตัวอย่าง บางครั้งสิ่งเหล่านี้จะไม่มีอยู่เนื่องจากผู้ปกครองขี้เกียจเกินกว่าที่จะเติมลงในกล่องทั้งหมด เราเพิ่ม "ไม่มี" หรือ "หายไป" หรือ "ไม่รู้จัก" ในข้อมูลของเราเพื่อปรับปรุงการค้นหาของเราหรือไม่? ไม่เพราะอาจมีคนแปลก ๆ ที่เปลี่ยนชื่อเป็นค่าเหล่านี้และเมื่อเราพิมพ์ข้อมูลออกมาเราไม่รู้ว่าเราจะต้องรวมมันหรือไม่ มันเป็นตัวอย่างที่ง่าย แต่ก็เข้าถึงได้ไกล เรารู้เกี่ยวกับ NULL และมีฟังก์ชั่นที่คาดการณ์ได้เพื่อจัดการกับมัน คุณไม่สามารถเขียนโค้ดนี้ได้ดีกว่านี้

หากไม่มีคำตอบ (หรือ NULL) ไม่ใช่คำตอบที่ถูกต้องสำหรับคำขอป้อนข้อมูลของคุณแล้วไม่อนุญาตในแอปพลิเคชันหรือในฐานข้อมูลหากเป็นการตอบสนองที่ดีคุณต้องอนุญาตทั้งในแอปพลิเคชันและฐานข้อมูลของคุณ มันเป็นการตอบสนองที่ถูกต้อง หากเป็นส่วนหนึ่งของชุดการตอบกลับที่ถูกต้องฐานข้อมูลของคุณจะต้องได้รับการออกแบบเพื่อเก็บไว้ ในที่สุดคุณก็ไม่ได้พูดว่าเฮ้เขตข้อมูลจำนวนน่าเบื่อมากให้เก็บตัวเลขใน blobs และใช้รูปภาพของสัตว์ป่าเพื่อเป็นตัวแทนของแต่ละหมายเลขเพราะนั่นคือถั่ว เรายังไม่ได้ตัดสินใจด้วยว่าเราไม่ชอบตัวอักษร B และเหมือนฝันร้ายอันโหดร้ายของเซซามีสตรีทแทนที่มันด้วย # ในข้อมูลของเรา หาก B ไม่ใช่คำตอบที่เราต้องการเราจะบอกผู้ใช้ว่า "เฮ้คุณไม่สามารถใส่ B ที่นี่" แล้วทำไมการรักษาแบบ null จึงแตกต่างกัน?

ดังนั้นหลีกเลี่ยงค่า null ที่คุณไม่ต้องการในระดับแอปพลิเคชันและจัดการกับพวกมันในฐานข้อมูลของคุณที่คุณยอมรับพวกเขาเป็นอย่างอื่นเช่นเดียวกับยีราฟ + giraffe = hippo การถกเถียงข้อมูลไร้สาระของคุณจะทำให้คุณเดือดร้อน


2
พ่อแม่ของฉันไม่ขี้เกียจและฉันไม่มีชื่อกลางโดยวิธี ไม่ใช่ทุกคนที่อาศัยอยู่ในสหรัฐอเมริกา
ypercubeᵀᴹ

1
มันหมายถึงการเป็นตัวอย่างที่อ่อนโยนไม่ผิดกฎหมาย แน่นอนว่ามีหลายคนที่ไม่มีชื่อกลาง (จุดแรก) ด้วยเหตุผลที่ถูกต้องหลายประการ (ประเด็นหลัก) ว่างในคอลัมน์นี้จะบอกอะไรคุณไม่ได้ว่าทำไมมันหายไป ไม่แน่ใจเกี่ยวกับมุมมองทางภูมิศาสตร์ทางการเมืองของคุณ - ฉันไม่ได้อาศัยอยู่ในสหรัฐอเมริกา แต่จริงๆแล้วมีชื่อกลาง มันยากที่จะสร้างสมมุติฐานจากข้อมูลที่ขาดหายไปซึ่งฉันเดาได้

ไม่มีการกระทำความผิด ฉัน upvote คำตอบของคุณจริง ฉันคิดว่าคุณโดนเล็บด้วยประเด็นหลักของคุณว่ามีความแตกต่างระหว่างการไม่ยอมรับ / อนุญาตให้ Nulls ในฐานข้อมูลและแทนที่ Nulls ด้วยค่าเวทย์มนตร์
ypercubeᵀᴹ

5
ฉันจะรักมันถ้าชื่อกลางของฉันคือ "-5000"! : D
Philᵀᴹ
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.