SQL: สตริงว่างกับค่า NULL


72

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

สมมติว่าฉันมีตารางที่มีข้อมูลส่วนบุคคล (ชื่อ, วันเกิด, ฯลฯ ) โดยที่หนึ่งในคอลัมน์คือที่อยู่อีเมลที่มีประเภท varchar เราคิดว่าด้วยเหตุผลบางคนบางคนอาจไม่ต้องการให้ที่อยู่อีเมล เมื่อแทรกข้อมูลดังกล่าว (ไม่มีอีเมล) ลงในตารางมีสองตัวเลือกที่ใช้ได้: ตั้งค่าเซลล์เป็น NULL หรือตั้งค่าเป็นสตริงว่าง ('') สมมติว่าฉันทราบถึงผลกระทบทางเทคนิคทั้งหมดของการเลือกโซลูชันหนึ่งมากกว่าโซลูชันอื่นและฉันสามารถสร้างแบบสอบถาม SQL ที่ถูกต้องสำหรับสถานการณ์ใดสถานการณ์หนึ่ง ปัญหาคือแม้เมื่อค่าทั้งสองแตกต่างกันในระดับเทคนิคพวกเขาจะเหมือนกันในระดับตรรกะ หลังจากดู NULL และ '' ฉันได้ข้อสรุปเดียว: ฉันไม่รู้ที่อยู่อีเมลของผู้ชายคนนั้น ไม่ว่าฉันจะพยายามมากแค่ไหน ฉันไม่สามารถส่งอีเมลโดยใช้ NULL หรือสตริงว่างเปล่าได้ดังนั้นเซิร์ฟเวอร์ SMTP ส่วนใหญ่ก็เห็นด้วยกับเหตุผลของฉัน ดังนั้นฉันมักจะใช้ค่า NULL ที่ฉันไม่ทราบค่าและพิจารณาสตริงว่างเปล่าเป็นสิ่งที่ไม่ดี

หลังจากการพูดคุยอย่างเข้มข้นกับเพื่อนร่วมงานฉันมาด้วยคำถามสองข้อ:

  1. ฉันถูกสมมติว่าการใช้สตริงว่างเปล่าสำหรับค่าที่ไม่รู้จักทำให้ฐานข้อมูล "โกหก" เกี่ยวกับข้อเท็จจริงหรือไม่ เพื่อความแม่นยำมากขึ้น: การใช้ความคิดของ SQL เกี่ยวกับสิ่งที่มีค่าและสิ่งที่ไม่ฉันจะสรุป: เรามีที่อยู่อีเมลเพียงแค่ค้นหาว่ามันไม่ได้เป็นโมฆะ แต่ต่อมาเมื่อพยายามส่งอีเมลฉันจะได้ข้อสรุปที่ขัดแย้งกัน: ไม่เราไม่มีที่อยู่อีเมลที่ @! # $ ฐานข้อมูลต้องโกหก!

  2. มีสถานการณ์เชิงตรรกะใด ๆ ที่สตริงว่าง '' อาจเป็นผู้ให้บริการที่ดีของข้อมูลสำคัญ (นอกเหนือจากค่าและไม่มีค่า) ซึ่งจะลำบาก / ไม่มีประสิทธิภาพในการจัดเก็บด้วยวิธีอื่น (เช่นคอลัมน์เพิ่มเติม) ฉันเคยเห็นโพสต์มากมายที่อ้างว่าบางครั้งมันเป็นการดีที่จะใช้สตริงว่างพร้อมกับค่าจริงและค่า NULLs แต่จนถึงขณะนี้ยังไม่เห็นสถานการณ์ที่จะเป็นตรรกะ (ในแง่ของการออกแบบ SQL / DB)

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


11
คุณรู้หรือไม่ว่าใน Oracle สตริงว่างเปล่าเป็น NULL
281377

8
@ammoQ: การปฏิบัติต่อสตริงที่มีความยาวเป็นศูนย์ของออราเคิลนั้นไม่ได้มาตรฐาน นอกจากนี้''แม้ใน Oracle, NULLไม่ได้เช่นเดียวกับ ยกตัวอย่างเช่นการกำหนดCHAR(1)คอลัมน์ค่า''จะส่งผล' '(เช่นพื้นที่) NULLไม่ใช่ นอกจากนี้หาก Jacek ถูกใช้ Oracle คำถามนี้อาจจะไม่ได้เกิดขึ้น :-)
คณบดีฮาร์ดิ้ง

2
คณบดี: คุณพูดถูกเกี่ยวกับตัวอย่างถ่าน (1) แต่นั่นก็ยังเป็น WTF อีกอันนับตั้งแต่'' IS NULLประเมินเป็นtruePL / SQL
281377

"ฉันถูกสมมติว่าการใช้สตริงว่างสำหรับค่าที่ไม่รู้จักทำให้ฐานข้อมูล" โกหก "เกี่ยวกับข้อเท็จจริง" หากผู้ใช้ทางธุรกิจของคุณไม่สนใจเกี่ยวกับสิ่งที่ไม่รู้จัก vs ความว่างเปล่าการโกหกนั้นสำคัญหรือไม่
Andy

หากคุณต้องไปเส้นทางของการใช้สตริง ... โปรดได้โปรดตรวจสอบให้แน่ใจว่ามันว่างเปล่า เพื่อประโยชน์ของนักพัฒนาทั้งหมดอย่าปล่อยให้สตริงที่มีช่องว่างในนั้นเป็นตัวแทนของค่าที่ไม่รู้จัก ฉันขอร้องคุณ
Airn5475

คำตอบ:


83

ฉันจะบอกว่าNULLเป็นตัวเลือกที่ถูกต้องสำหรับ "ไม่มีที่อยู่อีเมล" มีที่อยู่อีเมล "ไม่ถูกต้อง" จำนวนมากและ "" (สตริงว่าง) เป็นที่อยู่เดียว ตัวอย่างเช่น "foo" ไม่ใช่ที่อยู่อีเมลที่ถูกต้อง "a @ b @ c" ไม่ถูกต้องเป็นต้น ดังนั้นเพียงเพราะ "" ไม่ใช่ที่อยู่อีเมลที่ถูกต้องไม่มีเหตุผลที่จะใช้เป็นค่า "ไม่มีที่อยู่อีเมล"

ฉันคิดว่าคุณพูดถูกว่า "" ไม่ใช่วิธีที่ถูกต้องในการพูดว่า "ฉันไม่มีค่าสำหรับคอลัมน์นี้" "" คือค่า

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


5
เห็นด้วยอย่างสิ้นเชิง. เป็นโมฆะมีเหตุผล เลือก COUNT (*) จาก YOURTABLE อีเมลอยู่ที่ไหน [ไม่] ค่า NULL เป็นวิธีการทำไม่ใช่การเปรียบเทียบสตริงซึ่งจะมีแนวโน้มที่จะช้ากว่า
LudoMC

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

9
@Alexey - NULL หมายความว่าไม่มีค่า ตามที่คนอื่น ๆ ได้ชี้ให้เห็นสตริงว่างเปล่าเป็นค่า
Ramhound

3
@Ramhound ฉันยอมรับว่าสตริงว่างคือค่าและค่า NULL นั้นหมายถึง "ไม่มีค่า" ฉันเพิ่งอธิบายการตีความของฉันของ "ไม่มีค่า" ในความคิดของฉันมันไม่เหมือนกับ "คนที่ไม่ได้เปิดบัญชีอีเมลใด ๆ " ค่อนข้าง "ไม่มีที่อยู่อีเมลที่บันทึกไว้สำหรับบุคคลนั้น"
Alexey

5
@Ramhound NULL หมายความว่าไม่มีค่าใด ๆ คนที่ไม่มีชื่อกลางไม่มีค่า ดังนั้น NULL ควรใช้ในคอลัมน์เริ่มต้นกลางเช่นกัน ... ซึ่งตรงข้ามกับอาร์กิวเมนต์ที่แสดงในคำตอบนี้อย่างสมบูรณ์
Izkata

41

ในขณะที่เห็นด้วยกับความคิดเห็นข้างต้นฉันจะเพิ่มอาร์กิวเมนต์นี้เป็นแรงจูงใจหลัก:

  1. เห็นได้ชัดว่าโปรแกรมเมอร์ทุกคนกำลังดูฐานข้อมูลว่าเขตข้อมูลที่มีค่า NULL เป็นเขตข้อมูลเพิ่มเติม (เช่นบันทึกไม่ต้องการข้อมูลสำหรับคอลัมน์นั้น)
  2. ถ้าคุณทำเครื่องหมายเขตข้อมูลไม่เป็นโมฆะโปรแกรมเมอร์ใด ๆ ควรสันนิษฐานว่าเป็นเขตข้อมูลที่จำเป็น
  3. ในฟิลด์ที่อนุญาตให้มีค่า Null โปรแกรมเมอร์ควรคาดหวังให้เห็นค่า Null แทนที่จะเป็นสตริงว่าง

เพื่อประโยชน์ในการเข้ารหัสด้วยตนเองของเอกสารด้วยตนเองให้ใช้ NULL แทนสตริงว่าง


4
+1 นี่คืออาร์กิวเมนต์ "ความประหลาดใจน้อยที่สุด" ที่เกี่ยวกับนักพัฒนากับสตริงที่ว่างเปล่า ไม่มีนักพัฒนาที่มาภายหลังจะคาดหวังว่าจะใช้สตริงว่างเพื่อแสดงว่า "ไม่มีที่อยู่อีเมล"
โทมัส

6

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

นี่คือลิงค์ที่มีคะแนนที่คุณควรพิจารณา: https://stackoverflow.com/questions/405909/null-vs-empty-when-dealing-with-user-input/405945#405945

--- แก้ไข (ตอบกลับความคิดเห็นโทมัส) ---

ฐานข้อมูลไม่สามารถใช้งานได้หากไม่มีแอปพลิเคชันที่ใช้ การกำหนดค่า NULL หรือ '' ไม่มีค่าหากแอปพลิเคชันไม่สามารถใช้งานได้อย่างถูกต้อง

ลองพิจารณาตัวอย่างหนึ่งที่ผู้ใช้กรอกแบบฟอร์ม LONG แล้วกด Enter ซึ่งจะส่งคำขอไปยังเซิร์ฟเวอร์ เขาอาจอยู่ในระหว่างการป้อนอีเมลของเขา ส่วนใหญ่คุณอาจต้องการเก็บสิ่งที่เขามีในฟิลด์อีเมลดังนั้นในภายหลังเขาสามารถทำมันให้เสร็จ ถ้าเขาป้อนตัวละครเพียงตัวเดียวล่ะ ถ้าเขาป้อนอักขระหนึ่งตัวแล้วลบออก เมื่อไม่จำเป็นต้องใช้อีเมลบางครั้งผู้ใช้ต้องการลบ: วิธีที่ง่ายที่สุดในการล้างฟิลด์ นอกจากนี้ในกรณีที่อีเมลไม่จำเป็นต้องมีการตรวจสอบก่อนส่ง

อีกตัวอย่าง: ผู้ใช้ระบุอีเมลเป็น spamto @ [bigcompany] .com - ในกรณีนี้ไม่จำเป็นต้องส่งอีเมลถึงแม้ว่าจะมีอยู่จริงและใช้ได้ก็ตาม (และอาจมีอยู่) การส่งหนึ่งอาจถูก แต่ถ้ามีผู้ใช้ 10K กับอีเมลดังกล่าวสำหรับการสมัครสมาชิกรายวันการตรวจสอบดังกล่าวอาจประหยัดเวลาได้มาก


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

ฉันดีใจที่คุณเรียนรู้วิธีการเขียนและแสดงความคิดเห็นในเว็บไซต์นี้ :) ฉันยังเชื่อว่า DB ควรสนับสนุนแอปพลิเคชันที่ใช้งานอยู่ ตรวจสอบคำตอบที่แก้ไขแล้วของฉัน
Konstantin Petrukhnov

4
ฐานข้อมูลไม่สามารถใช้งานได้หากไม่มีแอปพลิเคชันที่ใช้ จากประสบการณ์ของฉันมันไม่จริงและสายตาสั้น เกือบทุกครั้งที่ฐานข้อมูลถูกใช้นอกแอปพลิเคชันที่ออกแบบมา โดยทั่วไปฐานข้อมูลจะอยู่ได้นานกว่าแอปพลิเคชันที่สร้างขึ้น ฐานข้อมูลควรได้รับการออกแบบมาเพื่อรวบรวมข้อเท็จจริงเกี่ยวกับธุรกิจและ UI ควรสร้างขึ้นเพื่ออ่านและเขียนไปยังฐานข้อมูลไม่ใช่วิธีอื่น การออกแบบเชิงสัมพันธ์เป็นแนวคิดที่แตกต่างไปจากการออกแบบแอพพลิเคชั่นอย่างสิ้นเชิง
โทมัส

2
ตัวอย่างที่ฐานข้อมูลนั้นไม่ได้ใช้แต่เพียงผู้เดียวโดยเดิมใช้: รายงานการผสานรวมกับระบบอื่น ๆ
โทมัส

1
ตามที่ Thomas ระบุว่า DB สามารถและบ่อยครั้งที่มีการใช้งานมากกว่าหนึ่งแอปพลิเคชันซึ่งเพิ่มน้ำหนักให้กับแนวคิดในการรักษาข้อมูล DB ของคุณให้สะอาด หากคุณไม่ต้องการ / ไม่สามารถจัดการ NULL ในแอปพลิเคชันของคุณคุณสามารถแทนที่ "Magic values" (คำอธิบายที่ดี Thomas) ที่ชั้นการเข้าถึงข้อมูลของคุณ วิธีนี้แอปพลิเคชันในอนาคตที่ต้องการเข้าถึงฐานข้อมูลไม่จำเป็นต้องทราบเกี่ยวกับ / สอดคล้องกับค่าเวทย์มนตร์ของแอปพลิเคชันดั้งเดิม
bendemes

5

ฉันคิดว่าคำตอบของ Dean Hardings ครอบคลุมเรื่องนี้เป็นอย่างดี ที่กล่าวว่าฉันอยากจะพูดถึงว่าเมื่อพูดถึง NULLs vs สตริงว่างในระดับ DB คุณควรมีความคิดเกี่ยวกับชนิดข้อมูลอื่น ๆ ของคุณ คุณจะจัดเก็บวันที่ขั้นต่ำเมื่อไม่มีการระบุวันที่หรือไม่? หรือ -1 เมื่อไม่ได้ใส่ค่า int การจัดเก็บค่าเมื่อคุณไม่มีค่าหมายความว่าคุณต้องติดตามช่วงค่าที่ไม่ใช่ทั้งหมด อย่างน้อยหนึ่งชนิดสำหรับแต่ละประเภทข้อมูล (อาจมากกว่าที่คุณได้รับในกรณีที่ -1 เป็นค่าจริงดังนั้นคุณต้องมีทางเลือกอื่น ๆ ) หากคุณต้องการ / ต้องการทำสิ่งที่ "เหลวไหล" ในระดับแอปพลิเคชันซึ่งเป็นสิ่งหนึ่ง แต่ไม่จำเป็นต้องทำให้ข้อมูลของคุณสกปรก


2
+1 - นี่คือสิ่งที่ฉันเรียกว่า "Magic Value Solution" เราต้องคิดค่าเวทย์มนตร์สำหรับแต่ละประเภทข้อมูลเพื่อแสดงว่าไม่มีค่า นอกจากนี้ในบางคอลัมน์ค่าเวทย์มนตร์ทั่วไปเป็นหรือกลายเป็นค่าที่ถูกต้องตามกฎหมายและจึงจำเป็นต้องมีค่าเวทย์ใหม่
โทมัส

5

น่าเสียดายที่ Oracle สับสนการแสดงสตริง VARCHAR ของศูนย์ความยาวด้วยการเป็นตัวแทนของ NULL พวกเขาทั้งสองมีการแสดงภายในโดยไบต์เดียวที่มีค่าเป็นศูนย์ นี่ทำให้การสนทนายากขึ้นมาก

จำนวนมากของความสับสนโดยรอบศูนย์โมฆะรอบสามมูลค่าตรรกะ พิจารณารหัสเทียมต่อไปนี้:

if ZIPCODE = NULL
    print "ZIPCODE is NULL"
else if ZIPCODE <> NULL
    print "ZIPCODE is not NULL"
else print "Something unknown has happened"

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

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

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

นอกจากนี้โปรดระวังว่าแม้ว่าคุณจะหลีกเลี่ยง NULLS ทั้งหมดในข้อมูลที่เก็บไว้ (ฟอร์มปกติที่หก) หากคุณเข้าร่วมภายนอกคุณยังคงต้องรับมือกับ NULLS


4

ใช้เป็นศูนย์

ไม่มีจุดใดในการจัดเก็บค่า '' เมื่อทำการสร้างฟิลด์ในตารางที่ nullable จะทำ ทำให้ข้อความค้นหาชัดเจนขึ้น

แบบสอบถาม SQL ใดที่ชัดเจนกว่าและอ่านได้ถ้าคุณต้องการค้นหาผู้ใช้ที่มีที่อยู่อีเมล

  1. SELECT * FROM Users WHERE email_address != ''

  2. SELECT * FROM Users WHERE email_address IS NOT NULL

  3. SELECT * FROM Users WHERE email_address != '' and email_address IS NOT NULL

ฉันจะบอกว่า 2 คือ แม้ว่า 3 จะแข็งแกร่งกว่าในกรณีที่มีการจัดเก็บข้อมูลไม่ดี

สำหรับกรณีของที่อยู่อีเมลในแบบฟอร์มซึ่งเป็นตัวเลือกควรแสดงในตารางด้วย ใน SQL มันเป็นเขตข้อมูลที่ไม่มีค่าซึ่งหมายความว่ามันไม่เป็นที่รู้จัก

ฉันไม่สามารถนึกถึงมูลค่าทางธุรกิจที่สมเหตุสมผลในการจัดเก็บสตริงว่างในตารางอื่นนอกเหนือจากการออกแบบที่ไม่ดี มันเหมือนกับการเก็บค่าสตริงเป็น 'NULL' หรือ 'BLANK' และให้นักพัฒนาสันนิษฐานว่ามันเป็นโมฆะหรือสตริงว่าง สำหรับฉันมันเป็นการออกแบบที่ไม่ดี ทำไมต้องเก็บไว้เมื่อมีค่าว่าง?

เพียงใช้ NULL แล้วคุณจะทำให้ทุกคนมีความสุขมากขึ้น

ข้อมูลเพิ่มเติม:

SQL ใช้ระบบลอจิกที่มีค่าสามระบบ: True, False และ Unknown

สำหรับดีขึ้นและคำอธิบายรายละเอียดผมขอแนะนำให้นักพัฒนาในการอ่าน: SQL แบบสอบถาม - เกินความจริงและเท็จ


3

สำหรับคำถามทางเทคนิคเฉพาะปัญหาก็คือไม่เป็นโมฆะ VS เปล่าสตริงมันเป็นความล้มเหลวในการตรวจสอบ สตริงว่างไม่ใช่ที่อยู่อีเมลที่ถูกต้อง!

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

สตริงว่างจะเป็นอินพุตที่ถูกต้องในการตอบคำถาม: mime พูดอะไรกับยีราฟบ้าง


แม้จะมีเจตนาที่ดีที่สุดในโลกการตรวจสอบความถูกต้องอาจไม่สามารถแก้ปัญหานี้ได้ - เขาอาจยังต้องใช้วิธีการจัดการกับแถวที่คอลัมน์ทั้งหมดจะต้องได้รับคุณค่าบางอย่าง ในกรณีนั้นคำถามจะยังคงอยู่ - มูลค่าใดที่จะใช้เมื่อไม่มีค่า และแน่นอนคำตอบคือ: ค่าที่ระบุว่าไม่มีค่า ในฐานข้อมูล NULL นี้โดยทั่วไป
jmoreno

2

ฉันคิดว่ามีเหตุผลที่มี NULL และสตริงว่าง:

  • คุณมีที่อยู่อีเมลที่ถูกต้อง: me@example.com
  • คุณไม่มี (และอาจจะขอหนึ่ง): NULL
  • คุณรู้ว่าบุคคลนี้ไม่มีที่อยู่อีเมล: Empty String.

อย่างไรก็ตามฉันจะไม่แนะนำและใช้เขตข้อมูลแยกต่างหากเพื่อถามว่าคุณทราบหรือไม่ว่าไม่มีอยู่


1

คำถามที่ฉันเข้าใจคือการตีความของ NULL และสตริงว่างควรเลือก นี้ขึ้นอยู่กับวิธีการหลายรัฐฟิลด์ particualar สามารถในการ

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


1

โดยพื้นฐานแล้วในระดับตรรกะไม่มีความแตกต่างระหว่างค่า "ไม่ถูกต้อง" และ "ไม่มีการป้อนข้อมูลของผู้ใช้" พวกเขามักใช้เวลา "กรณีพิเศษ" เกือบทั้งหมด กรณีข้อผิดพลาด

การมีค่า null จะใช้พื้นที่เพิ่มเติม: ceil (columns_with_null / 8) ในหน่วยไบต์ / ต่อแถว

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

และข้อมูลของคุณอาจกลายเป็นระเบียบ ในโลกที่สมบูรณ์แบบคุณจะพูดว่า "ข้อมูลจะถูกต้องเสมอและฉันจะจดจำ" ... แต่เมื่อผู้คนต้องทำงานเป็นทีมและไม่ใช่ทุกคนที่อยู่ในระดับของคุณมันไม่ใช่เรื่องแปลกที่จะเห็นว่าที่ไหน (aa xx <> '' และ bb.zz ไม่เป็นโมฆะ)

ดังนั้นแทนที่จะแก้ไขสมาชิกในทีมของฉันทุกวันฉันเพิ่งบังคับใช้กฎง่าย ๆ ไม่มีค่าว่างไม่เคย!

การนับค่าที่ไม่ใช่ค่า NULL นั้นเร็วกว่า ... คำถามง่าย ๆ คือสิ่งที่คุณต้องทำเพื่ออะไร


ฉันจำได้ว่าอ่าน NULL ที่ใช้จริงเป็นค่าใช้จ่าย (ทั้งในแง่ของการคำนวณและการจัดเก็บ) สำหรับฐานข้อมูล จุดที่ดีในการนำสูตรนั้นขึ้นมา
Jacek Prucia

อย่าลืมว่าVARCHARคอลัมน์จะมีอย่างน้อย 1 ไบต์เพื่อเก็บความยาวของสตริงแม้ว่าจะเป็นศูนย์
dan04

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

3
ไม่มีค่าเป็นศูนย์ นี่คือวิธีการนกกระจอกเทศ "เราจะติดหัวของเราในทรายและประกาศว่าไม่มีค่าขาดหายไป" ซึ่งมักจะนำไปสู่ ​​Magic Value Solution ที่คุณต้องใช้ค่าวิเศษสำหรับข้อมูลแต่ละประเภทเพื่อแสดงว่าไม่มีค่า
โทมัส

1

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

ในโปรแกรมฉันไม่ชอบ null / ไม่มีอะไร มีข้อยกเว้นเล็กน้อย แต่มีเพียงแค่นั้น และข้อยกเว้นเหล่านั้นเป็นเพียงการใช้งานที่ไม่ดีจริงๆ

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

แนวคิดของการมีความหมายว่างเปล่าคือโรงเรียนเก่าและเป็นสิ่งที่โปรแกรมเมอร์ยุคใหม่ต้องหลีกเลี่ยง

แม้ในการออกแบบฐานข้อมูลเหตุใดฟิลด์อีเมลจึงไม่สามารถอนุญาตโมฆะและมีสตริงที่มีความยาวเป็นศูนย์และมีฟิลด์อื่นที่ระบุว่าผู้ใช้ป้อนบางสิ่งหรือไม่ เป็นบิตที่ถามของ DBMS หรือไม่? ในความคิดของฉัน DB ไม่ควรจัดการกับตรรกะทางธุรกิจหรือตรรกะการแสดงผล มันไม่ได้ถูกสร้างขึ้นเพื่อสิ่งนั้นและทำให้การจัดการกับมันแย่มาก


เหตุใดเขตข้อมูลอีเมลจึงไม่อนุญาตให้มีค่า Null และมีสตริงที่มีความยาวเป็นศูนย์ - เพียงแค่ใส่: เนื่องจากผู้พัฒนาที่รู้อะไรเกี่ยวกับฐานข้อมูลจะไม่คาดหวังว่าสตริงว่างที่มีความหมายเวทย์มนตร์ คุณกำลังพยายามสร้างมูลค่ามายากลของคุณเองเพื่อแสดงสิ่งที่มีอยู่แล้วในทุกฐานข้อมูล: แนวคิดที่จะแสดงถึงการขาดค่า ทำไมต้องคิดค้นล้อใหม่ นอกจากนี้แนวคิดของ NULLS อยู่ไกลจากโรงเรียนเก่า Nulls เป็น keystone เพื่อทำความเข้าใจการออกแบบฐานข้อมูลเชิงสัมพันธ์
โทมัส

ฮ่า ๆ. เช่นเดียวกับที่ฉันพูดจากมุมมองของโปรแกรมเมอร์ nulls มักจะเจ็บปวดในก้นและแทบจะไม่จำเป็นสำหรับ BUSINESS LOGIC โดยส่วนตัวในฐานะนักพัฒนาฉันไม่สนใจเรื่องการออกแบบเชิงสัมพันธ์มากนัก ถ้าฉันทำฉันจะเป็น DB เพื่อน ถ้าฉันได้รับโมฆะจากฐานข้อมูลฉันมักจะแปลงเป็นสิ่งที่มีเหตุผลเช่นสตริงว่างแล้วปล่อยให้การออกแบบ OOP อันรุ่งโรจน์ของฉันเป็นมายากล กรอบการทำงานจะดูแล DBAs โมฆะเหล่านั้นบังคับให้โลก ฉันรู้ว่า DB เป็ดต้องจัดการกับมันและฉันรู้สึกสำหรับคุณ แต่ในฐานะโปรแกรมเมอร์ฉันไม่จำเป็นต้องทำ ฉันมีทางออกที่ดีกว่า
ElGringoGrande

คุณ "ไม่เคย" ต้องจัดการกับโมฆะ ดังนั้นสิ่งที่คุณอธิบายคือวิธีการแก้ปัญหานกกระจอกเทศรวมกับโซลูชั่นค่ามายากล "ฉันจะเพิกเฉยต่อความจริงที่ว่ามีค่าขาดหายไปและฉันจะแปลงจำนวนเต็มเป็น null ทั้งหมด" จนกระทั่งถึงวันที่ -1 จะมีค่าจริง ควรสังเกตว่าหนึ่งในเหตุผลที่ MS เพิ่มชื่อ generics ให้กับ. NET คือการจัดการกับความไม่ตรงกันของอิมพีแดนซ์ขนาดใหญ่ระหว่างฐานข้อมูลและรหัสแอพพลิเคชั่น "โมฆะโง่" เหล่านั้นมีอยู่ในตรรกะทางธุรกิจด้วย
โทมัส

ความจริงที่ว่าจำนวนเต็มบางอย่างไม่อยู่ในฐานข้อมูล (หรือเป็นโมฆะ) ไม่ได้หมายความว่าฉันต้องแสดงด้วย -1 หรือ evan เป็นโมฆะ (int) หากคุณคิดว่าเป็นวิธีเดียวที่จะจัดการกับค่า Null คุณจะไม่เข้าใจการเขียนโปรแกรมที่ดีมาก โปรดจำไว้ว่า null ไม่เหมือนกับสิ่งใด เช่นเดียวกับที่คุณพูด null แสดงถึงตัวยึดตำแหน่งสำหรับค่าที่ขาดในโครงสร้างข้อมูลบางชนิด มันหมายถึงบางสิ่ง ตรรกะทางธุรกิจไม่ค่อย (ซึ่งไม่เหมือนไม่เคย) ต้องการแนวคิดนี้เพราะเป็นเรื่องเกี่ยวกับคนที่ใช่ไม่ใช่ข้อมูล และเมื่อไหร่ที่มันเป็นโมฆะก็เป็นวิธีที่ดีที่สุดในการแสดงสิ่งนี้
ElGringoGrande

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

-1

ฉันไม่คิดว่ามันสำคัญมาก แต่ฉันชอบดีกว่าเมื่อมี NULL อยู่

เมื่อฉันดูข้อมูลที่แสดงในตาราง (เช่นใน SQL Server Management Studio) ฉันสามารถแยกความแตกต่างของค่าที่หายไปได้ดีกว่าถ้ามันบอกว่า NULL และพื้นหลังมีสีต่างกัน

ถ้าฉันเห็นพื้นที่ว่างฉันมักจะสงสัยว่ามันว่างเปล่าจริง ๆ หรือมีช่องว่างหรือตัวละครที่มองไม่เห็น ด้วย NULL มันรับประกันว่าว่างเปล่าตั้งแต่แรกเห็น

ป้อนคำอธิบายรูปภาพที่นี่

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


นี้ไม่ได้ดูเหมือนจะนำเสนออะไรที่สำคัญกว่าจุดทำและอธิบายในก่อน 12 คำตอบ
ริ้น

@gnat: ฉันไม่เห็นด้วยไม่มีใครในคำตอบที่กล่าวถึงแง่มุมของการดูข้อมูลของมนุษย์ มีเพียงค่า NULL เดียว แต่อาจมีค่ามากมายที่ดูเหมือนสตริงที่ว่างเปล่า (ไม่ใช่แค่ช่องว่าง แต่มีอักขระยูนิโค้ดที่มีพฤติกรรมแปลก ๆ มากมายเช่นกัน) ฉันไม่เห็นคำตอบอื่น ๆ ที่กล่าวถึงปัญหานี้
Tom Pažourek

เท่าที่ฉันสามารถบอกได้ว่านี่เป็นคำตอบที่ดีอันดับสองที่โพสต์เมื่อ 5 ปีที่แล้ว: "เห็นได้ชัดว่าโปรแกรมเมอร์ทุกคนกำลังดูฐานข้อมูล ... " ฯลฯ
gnat

@gnat: ฉันเห็นจุดของคุณแม้ว่าฉันคิดว่าผู้เขียนไม่ได้หมายถึงสิ่งเดียวกัน ฉันเชื่อว่าเขาเพิ่มเติมเกี่ยวกับ NULL ที่แสดงถึงฟิลด์ที่เป็นตัวเลือก แต่สตริงว่างสามารถใช้สำหรับฟิลด์ที่ต้องการได้เช่นกันดังนั้น NULL จึงมีเหตุผลมากกว่าสำหรับค่าที่หายไป ฉันเห็นด้วยกับเขา แต่คำตอบของฉันชี้ให้เห็นถึงความจริงที่ว่าสตริงว่างเปล่านั้นไม่โปร่งใสเหมือนค่า NULL เนื่องจากหลายสิ่งสามารถดูเหมือนสตริงว่างตั้งแต่แรกเห็นในขณะที่ไม่ใช่สตริงว่างเปล่า
Tom Pažourek
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.