ฉันควรใช้คีย์หลักหลายคอลัมน์หรือเพิ่มคอลัมน์ใหม่ได้หรือไม่


15

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

ดังนั้นข้อเสียบางอย่างที่ฉันอาจเห็นในวิธีการนี้หรือเหตุผลที่ฉันอาจต้องการคีย์คอลัมน์เดียวคืออะไร


2
ฉันไม่รู้ฉันคิดว่ามันน่าจะดีกว่านี้
FrustratedWithFormsDesigner

2
@FrustratedWithFormsDesigner มันอาจเป็นไปได้ แต่ฉันคิดว่ามันใช้งานได้เช่นกันเนื่องจากจุดเน้นของคำถามดูเหมือนจะอยู่ที่ "อะไรคือข้อดีและข้อเสียของวิธีการนี้" มากกว่า "ฉันจะทำ X อย่างไร"
อดัมเลียร์

@ แอนนาเลียร์♦: มันเป็น "ข้อดีข้อเสีย" เกี่ยวกับการตัดสินใจออกแบบที่จะมีผลกระทบโดยตรงและแน่นอนในการเขียนโค้ดดังนั้นฉันคิดว่า SO น่าจะเป็นสถานที่ที่ดีกว่า
FrustratedWithFormsDesigner

คำตอบ:


8

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

ลองดูที่ความสัมพันธ์หลายข้อกับหลายข้อสมมุติ:

นักเรียน * --- * คลาส

(นักเรียนสามารถอยู่ในหลายชั้นเรียนได้นักเรียนหลายคน)

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

นักเรียน 1 --- * การลงทะเบียน * --- 1 ชั้น

(นักเรียนสามารถมีการลงทะเบียนได้จำนวนมากการลงทะเบียนแต่ละครั้งสำหรับหนึ่งชั้นเรียน (หรือไปในทางตรงกันข้ามชั้นเรียนสามารถมีการลงทะเบียนจำนวนมากได้การลงทะเบียนแต่ละครั้งสำหรับนักเรียนหนึ่งคน)

ตอนนี้คุณสามารถค้นหาสิ่งต่าง ๆ เช่นจำนวนนักเรียนที่ลงทะเบียนเรียนวิชาเคมี 101 ในปีที่แล้ว หรือนักเรียนคนใดที่ John Doe ลงทะเบียนเรียนในขณะที่เข้าเรียนที่มหาวิทยาลัย Acme สิ่งนี้เป็นไปได้โดยไม่ต้องมีคีย์หลักแยกต่างหาก แต่เมื่อคุณมีคีย์หลักสำหรับการลงทะเบียนแบบสอบถามที่ง่ายกว่าน่าจะเป็นของการลงทะเบียนเหล่านี้ (โดย id) จำนวนนักเรียนที่ได้รับคะแนนผ่านคือเท่าใด

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


1
ดังนั้นคุณจะเพิ่มลงในตาราง StudentClass เมื่อมาถึงจุดนี้ StudentClass ได้กลายเป็นเอนทิตี้ที่ไม่ซ้ำ ... และควรได้รับชื่อเพื่อรับรู้เช่นการลงทะเบียน มันเป็นเรื่องง่าย แต่มีคุณค่ามากในการทำเช่นนี้!
Botis

8

มันสมเหตุสมผลแล้วที่จะมีคอลัมน์ id แยกต่างหาก เมื่อคุณต้องการได้รับบางสิ่งจากตารางฐานข้อมูลของคุณจะทำได้ง่ายกว่า:

SELECT whatever FROM table WHERE id=13

กว่า SELECT อะไรก็ได้จากตาราง WHERE col1 = 'val1' AND col2 = 'val2' และ col3 = 'val3'

ตัวอย่างเช่นในเว็บแอปพลิเคชันแปลเป็น URL ที่มีลักษณะดังนี้:

www.somewebsite.com/somepage.php?id=13

หรือเช่นนี้

www.somewebsite.com/somepage.php?col1=val1&col2=val2&col3=val3

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

3
ขออภัย ณ จุดนี้ฉันต้อง -1 เป็นA)มันไม่ใช่ขาวดำ การเพิ่มคอลัมน์ ID มาพร้อมกับเนกาทีฟเช่นที่ไหนและเมื่อไหร่ที่คุณสร้าง ID ใหม่นั้น นอกจากนี้ยังอาจส่งผลให้เพิ่มการเข้าร่วมหรือSELECTแบบสอบถาม และB)ฉันไม่มีความคิดใด ๆ ว่าสิ่งนี้จริงทำให้เกิดความต้องการ URL ประเภทใด (เว้นแต่ว่าคุณกำลังทำงานกับกรอบงานที่ไม่ดี) URL ที่ฉันไม่ได้มีสายการสอบถามใด ๆ ที่มีอยู่ในพวกเขาให้อยู่คนเดียว?id=13 ?col1=val1&col2=val2&col3=val3
นิโคล

2
@renesis: ไซต์นี้มีคำถามและผู้ใช้ที่ไม่ซ้ำกันซึ่งอยู่ใน URL แม้ว่านี่จะเป็นกรณีพิเศษเนื่องจากข้อมูลนั้นไม่เปลี่ยนแปลง
Michael K

1
@Renesis ส่วนใหญ่ (บางทีทั้งหมด) db ที่ทันสมัยมีประเภทคอลัมน์จำนวนเต็ม auto_increment ที่สามารถสร้าง ID ของโดยอัตโนมัติและปลอดภัยและรายงานพวกเขากลับมาผ่านการสืบค้น SQL หรือฟังก์ชั่นห้องสมุด หรือในสภาพแวดล้อมแบบกระจายคุณใช้แฮ็กแบบสุ่มขนาดใหญ่ บางฐานข้อมูลจะสร้างคอลัมน์ id ที่ซ่อนไว้ให้คุณถ้าคุณไม่มีหนึ่งในตารางแล้ว
GrandmasterB

@Michael - ฉันไม่ได้บอกว่า ID จะไม่เคยอยู่ใน URL แน่นอนพวกเขาเป็น หากคุณมี URL ที่แสดงแถวของข้อมูลใช่แล้วข้อมูลนั้นควรมี ID ที่ไม่ซ้ำกัน ยกเว้นบางส่วนของ URL จะให้ส่วนอื่น ๆ ของมัลติคีย์อยู่แล้ว @GrandmasterB ทั้งสอง บริษัท ที่ฉันเคยทำงานมานานกว่า 6 ปีซึ่งทั้งสองใช้ MySQL (หนึ่งยังรองรับ Oracle และ SQL Server) สามารถใช้การเพิ่มอัตโนมัติหรือแฮ็คแบบสุ่มขนาดใหญ่
นิโคล

8

โดยทั่วไปคุณถามว่าคุณควรจะใช้ตัวแทนหรือปุ่มธรรมชาติ (ในกรณีของคุณดูเหมือนคอมโพสิตคีย์ธรรมชาติ) นี่คือบทความที่ยอดเยี่ยม: http://www.agiledata.org/essays/keys.html

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

ตัวอย่างเช่นสมมติว่าคุณมีสองเอนทิตี: ที่อยู่และประเทศ

  • ความสัมพันธ์คือ: ที่อยู่ * ----- 1 ประเทศ
  • เอนทิตีประเทศนั้นเป็นคีย์: คู่ค่า (เช่นสหรัฐอเมริกา: สหรัฐอเมริกา, CA: แคนาดา, MX: เม็กซิโก, ฯลฯ ... )
  • หากต้องการสอบถามโครงสร้างนี้สำหรับที่อยู่ทั้งหมดในสหรัฐอเมริกา:

select * from Address where CountryCode = 'US'

  • หากต้องการดำเนินการค้นหาเดียวกันโดยใช้คีย์ตัวแทน:

select Address.* from Address join Country on Address.CountryID = Country.ID where Country.Code = 'US'

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


5

ขึ้นอยู่กับว่าคุณเข้าถึงข้อมูลอย่างไร หากคุณทำการค้นหาคีย์บางส่วนจำนวนมาก (ซึ่งคุณเลือกระเบียนโดยพูดเพียงสองสามคีย์) ดังนั้นคุณจะต้องเก็บคีย์หลายส่วนไว้ OTOH ถ้าคุณมีความสัมพันธ์แบบ 1: 1 จำนวนมากกับตารางอื่น ๆ มันอาจสมเหตุสมผลกว่าที่จะมีคีย์ตัวแทน


1

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

ครั้งหนึ่งที่ฉันเคยมีกุญแจธรรมชาติหลายคอลัมน์กัดฉันอยู่กับ ORM บางครั้งฉันอาจมีปัญหากับคีย์หลักหลายคอลัมน์โดยใช้ Linq To Entities


1

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

คุณสามารถสร้างดัชนีอื่นเพื่อจัดการกับค่าที่ไม่ซ้ำกัน

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


0

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

ฉันไม่พบความช่วยเหลือ (โดยเฉพาะที่เก็บข้อมูล) เมื่อจัดการกับตารางข้อเท็จจริง / รายละเอียด ตัวอย่างที่ยอมรับมาตรฐานของตารางข้อเท็จจริงการขายที่มี (customer_key, store_key, product_key) ที่มีปริมาณไม่สมเหตุสมผลนักที่จะมีคีย์ระดับระเบียน


0

การมี PK เป็นระบบการจัดการอัตโนมัติช่วยลดความยุ่งยากหากคุณพบว่าคีย์ผสมของคุณสามารถทำซ้ำได้


0

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

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