มันจะถือว่าเป็นแนวปฏิบัติที่ไม่ดีที่จะมี FK แบบ nullable หลายรายการบนตารางใน SQL Server หรือไม่


13

ในโครงสร้างฐานข้อมูลของฉันใน SQL Server ฉันมีผลิตภัณฑ์ 3 ประเภทที่ต้องการข้อมูลที่แตกต่างกันเกี่ยวกับการสั่งซื้อ ดังนั้นฉันสร้างหนึ่งของตารางและสามตารางการสั่งซื้อที่แตกต่างกัน:Customers , , ตารางคำสั่งซื้อทั้งหมดมีความสัมพันธ์แบบหนึ่งต่อหลายบนโต๊ะOrdersForProductAsOrdersForProductBsOrdersForProductCsCustomers

ฉันยังมีตารางอื่นที่Paymentsจะเก็บรายละเอียดการชำระเงินไว้ข้างใน แต่ฉันมีข้อสงสัยเกี่ยวกับวิธีการจัดโครงสร้างที่นี่

เนื่องจากฉันมีผลิตภัณฑ์หลายประเภทและลูกค้าอาจมีคำสั่งซื้อหลายผลิตภัณฑ์ในเวลาเดียวกันฉันจึงต้องเชื่อมโยงตารางคำสั่งซื้อทั้งสามนั้นเข้ากับPaymentsตาราง

ปัญหาอื่นคือลูกค้าอาจมีคำสั่งซื้อผลิตภัณฑ์เพียงประเภทเดียว ดังนั้นคอลัมน์ FK ในตารางจะต้องมีการPaymentsnullable

คำถามของฉันคือว่าnullableคอลัมน์ FK เหล่านั้นจะปวดหัวสำหรับฉันในระยะยาวหรือไม่? โดยทั่วไปแล้วจะถือว่าเป็นการปฏิบัติที่ไม่ดีที่จะมีคอลัมน์ FK ที่ไม่มีค่าว่างบนตารางหรือไม่


2
ตรวจสอบให้แน่ใจว่าคุณมีข้อ จำกัด ในการตรวจสอบเพื่อให้FK อย่างน้อยหนึ่งรายการนั้นไม่ว่าง
Damien_The_Unbeliever

3
หนึ่งคีย์ต่างประเทศ nullable เป็นหนึ่งมากเกินไป
nvogel

คำตอบ:


13

ฉันถามว่าทำไมคุณมีOrdersForProductXตารางเลย
อาจเป็นไปได้ว่าปัญหาของ FK ที่คุณถามเกี่ยวกับสามารถออกแบบได้ ...

หากตารางเหล่านี้มีโครงสร้างเดียวกันคุณก็ต้องมีProductTypeคอลัมน์ในบางOrderProductตาราง จากนั้นPaymentเพียงลิงก์ไปยังสิ่งนั้นด้วยหนึ่ง FK

หากตารางมีโครงสร้างที่แตกต่างกันฉันถือว่าพวกเขามีคุณสมบัติทั่วไปบางอย่าง ดังนั้นคุณสามารถมีOrderProductตารางทั่วไปจากนั้นตารางลูกที่เฉพาะเจาะจงต่อประเภทผลิตภัณฑ์ (ดูด้านล่าง) อีกครั้งPaymentเพียงเชื่อมโยงไปยังตาราง Commone ด้วย FK หนึ่งรายการ

นี่คือ "รูปแบบ superkey / subtype"

  • UQ1 คือ "super key" ใช้ foreign key บนตารางย่อย
  • แต่ละตารางย่อยมีคอมโพสิต PK และ FK บน (OrderID, ProductType)
  • แต่ละตารางย่อยจะมีข้อ จำกัด ในการตรวจสอบเพื่อ จำกัด ประเภทในตารางนั้น

OrderProduct

  • OrderID, PK, UQ1
  • ประเภทผลิตภัณฑ์ UQ1
  • CommonThing1
  • ...

OrderProductA

  • OrderID, PK, FK
  • ประเภทผลิตภัณฑ์, PK, FK, CHECK ProductType = A
  • ProductAThing1
  • ...

OrderProductB

  • OrderID, PK, FK
  • ประเภทผลิตภัณฑ์, PK, FK, CHECK ProductType = B
  • ProductBThing1
  • ...

4
@tugberk: สังเกตว่าคุณจะไม่มีNULLคอลัมน์ FK ด้วยวิธีการนี้
ypercubeᵀᴹ

"ถ้าตารางเหล่านี้มีโครงสร้างเดียวกัน"พวกเขาไม่มีโครงสร้างเดียวกัน
tugberk

5

หลีกเลี่ยง "คีย์ต่างประเทศ" ที่ไม่มีค่า พวกเขามีข้อเสียหลายประการ

ข้อ จำกัด ของแถวอ้างอิงไม่ได้ถูกบังคับใช้เสมอเมื่อคีย์ต่างประเทศมีค่าเป็นโมฆะ อย่างไรก็ตามพฤติกรรมเริ่มต้นนั้นไม่สอดคล้องกันระหว่าง DBMS ที่แตกต่างกัน DBMS บางตัวสนับสนุนตัวเลือกการกำหนดค่าเพื่อเปลี่ยนลักษณะการทำงานของคีย์ต่างประเทศที่ไม่มีค่าและบางตัวไม่ทำ ผู้พัฒนาและผู้ใช้ SQL อาจไม่ชัดเจนเกี่ยวกับข้อ จำกัด ของคีย์ต่างประเทศที่ไม่มีค่าใช้จ่ายจริง ๆ จากมุมมองความสมบูรณ์ของข้อมูล การย้ายฐานข้อมูลระหว่างผลิตภัณฑ์ DBMS หรือแม้กระทั่งระหว่างเซิร์ฟเวอร์ต่าง ๆ ที่ใช้ผลิตภัณฑ์เดียวกันอาจให้ผลลัพธ์ที่ไม่สอดคล้องกัน

เครื่องมือการออกแบบฐานข้อมูลเครื่องมือการรวมและซอฟต์แวร์อื่น ๆ ไม่สนับสนุนอย่างถูกต้องเสมอไปและผลลัพธ์ที่พวกเขาสร้างอาจผิด

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

คุณลักษณะการปรับให้เหมาะสมของแบบสอบถามบางอย่างที่อนุญาตให้เขียนซ้ำแบบสอบถามและการปรับให้เหมาะสมอื่น ๆ อาจไม่พร้อมใช้งานเมื่อคีย์ต่างประเทศเป็นโมฆะ

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

คีย์ต่างประเทศที่ Nullable นั้นไม่จำเป็นอย่างสมบูรณ์ คุณสามารถแยกคีย์ต่างประเทศออกเป็นตารางใหม่ได้เสมอหรือใช้รูปแบบ supertype / subtype เพื่อไม่ให้มีค่าว่าง ในความสนใจของความเรียบง่ายและความถูกต้องดังนั้นจึงเป็นการดีกว่าที่จะปล่อยให้เป็นโมฆะกว่าวางไว้


2

ฉันไม่เคยได้ยินมาก่อนเลยว่ามันเป็นการปฏิบัติที่ไม่ดีในการใช้คอลัมน์ FK ที่ไม่มีค่า เหมาะสำหรับคอลัมน์ที่อ้างอิงตารางอื่น แต่อาจไม่ได้กรอก (เช่นข้อมูลที่เป็นตัวเลือก)

(ทำไมคุณถึงคิดว่ามันจะเป็นปัญหา?)


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