เหตุใดจึงใช้หลายคอลัมน์เป็นคีย์หลัก (คีย์หลักแบบผสม)


109

ตัวอย่างนี้จะนำมาจาก w3schools

CREATE TABLE Persons
(
    P_Id int NOT NULL,
    LastName varchar(255) NOT NULL,
    FirstName varchar(255),
    Address varchar(255),
    City varchar(255),
    CONSTRAINT pk_PersonID PRIMARY KEY (P_Id,LastName)
)

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

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


1
@Martijn ปีเตอร์ส. เหตุใดคำตอบจึงถูกลบ
PerformanceDBA

คำตอบ:


119

ความเข้าใจของคุณถูกต้อง

คุณจะทำเช่นนี้ในหลาย ๆ กรณี ตัวอย่างหนึ่งคือในความสัมพันธ์ที่เหมือนและOrderHeader OrderDetailใน PK อาจจะOrderHeader OrderNumberใน PK OrderDetailอาจจะมีและOrderNumber LineNumberถ้าเป็นอย่างใดอย่างหนึ่งในสองคนนั้นก็จะไม่ซ้ำกัน แต่การรวมกันของทั้งสองจะรับประกันได้ว่าไม่เหมือนใคร

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


2
จะมีประโยชน์ไหมถ้าฉันใช้ branch_id และใช้การจำลองแบบระหว่างสองฐานข้อมูลจะแก้รหัสซ้ำกันหรือไม่ !!
Mhmd

11
โปรดทราบว่าในหลาย ๆ กรณีของการใช้คีย์หลักที่สร้างขึ้นคุณมักจะยังคงต้องการคีย์เฉพาะสำหรับค่าผสม
Bacon Bits

โปรดอธิบายเพิ่มเติมเกี่ยวกับ "บางคนชอบทางเดียวบางคนชอบทางอื่น"
ชื่อผู้ใช้

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

ข้อความนั้นมีไว้สำหรับ @Username ฉันลืมกำกับไป
MJB

26

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

Create Table Person(
PersonID int Not Null,
FirstName varchar(50),
LastName varchar(50),
Constraint PK_Person PRIMARY KEY (PersonID))

Create Table Group (
GroupId int Not Null,
GroupName varchar(50),
Constraint PK_Group PRIMARY KEY (GroupId))

Create Table GroupMember (
GroupId int Not Null,
PersonId int Not Null,
CONSTRAINT FK_GroupMember_Group FOREIGN KEY (GroupId) References Group(GroupId),
CONSTRAINT FK_GroupMember_Person FOREIGN KEY (PersonId) References Person(PersonId),
CONSTRAINT PK_GroupMember PRIMARY KEY (GroupId, PersonID))

คำอธิบายที่ดี: ฉันคิดว่าความต้องการของคุณลักษณะสำหรับความสัมพันธ์แบบ m-to-n (ในรูปแบบปกติ) เป็นกุญแจสำคัญ
Wolf

อาจเพิ่มคำอธิบายประโยชน์เล็กน้อยจะดีกว่า
Martian2049

10

ตัวอย่าง W3Schools ไม่ได้บอกว่าคุณควรใช้คีย์หลักแบบผสมและเป็นเพียงตัวอย่างไวยากรณ์โดยใช้ตารางตัวอย่างเดียวกับคีย์อื่น ๆ

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

1234     Jobs
1234     Gates

อ่านเพิ่มเติม: การอภิปรายคีย์หลักที่ยอดเยี่ยมหรือเพียงแค่ Google meaningless primary keysหรือแม้แต่อ่านคำถาม SOนี้

FWIW - 2 เซ็นต์ของฉันคือการหลีกเลี่ยงคีย์หลักแบบหลายคอลัมน์และใช้ฟิลด์ id ที่สร้างขึ้นเดียว (คีย์ตัวแทน) เป็นคีย์หลักและเพิ่มข้อ จำกัด เพิ่มเติม (ไม่ซ้ำกัน) หากจำเป็น


1
1) ลิงก์ "การอภิปรายคีย์หลักที่ยอดเยี่ยม" นั้นโง่เป็นพิเศษข้อมูลที่ให้บริการด้วยตนเองและเป็นเท็จ 2) ดัชนีบนคอลัมน์ที่ทำให้แถวไม่ซ้ำกันไม่สามารถหลีกเลี่ยงได้ รหัส "ตัวแทน" ที่มีดัชนีเป็นคอลัมน์เพิ่มเติมและดัชนีเพิ่มเติมเสมอ ค่อนข้างโง่เพราะซ้ำซ้อน และช้าลง
PerformanceDBA

2
"การอภิปรายคีย์หลักที่ยิ่งใหญ่" ไม่ใช่เรื่องโง่เขลา เป็นปัญหาที่ถูกต้องมากจากนักพัฒนาที่ไม่ใช่ผู้พัฒนา sql หรือ sql DBA และอย่าใช้เวลาทั้งหมดใน sql แม้แต่ใน sql ที่บริสุทธิ์ฉันก็อยากจะมีคีย์ที่สร้างขึ้นโดยอัตโนมัติที่ไม่มีความหมายเป็นคีย์หลักเมื่อเข้าร่วมมากกว่าที่จะต้องจำไว้ว่าต้องส่งข้อมูล n บิตไปรอบ ๆ การเป็นคีย์ธรรมชาติ ยินดีต้อนรับสู่มุมมองของคุณ แต่เราขอขอบคุณที่ไม่ดูถูก
Robert Paulson

4

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


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

3

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


3

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


1
1) ประสิทธิภาพ ไม่ได้อยู่ในแพลตฟอร์ม SQL (อาจอยู่ใน "sql" และฟรีแวร์หลอก) 2) ค่ากำหนดไม่เกี่ยวข้อง สิ่งที่ตารางต้องการเพื่อความสมบูรณ์มีความเกี่ยวข้อง 3) ID "ตัวแทน" ที่มีดัชนีเป็นคอลัมน์เพิ่มเติมและดัชนีเพิ่มเติมเสมอ นั่นจะช้ากว่าในทุกแพลตฟอร์ม เรื่องประสิทธิภาพคุณขัดแย้งกับตัวเอง 4) หากคุณไม่ทราบวิธีอัปเดต "รายการย่อยล้านรายการในตารางย่อย 215" อย่างถูกต้องให้ถามคำถาม
PerformanceDBA

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

3

คำถามที่สองของคุณ

สามารถใช้คอลัมน์ร่วมกันเป็นคีย์หลักในตารางได้กี่คอลัมน์

เป็นการใช้งานเฉพาะ: กำหนดไว้ใน DBMS จริงที่ใช้ [1], [2], [3]คุณต้องตรวจสอบข้อกำหนดทางเทคนิคของระบบฐานข้อมูลที่คุณใช้ บางอย่างมีรายละเอียดมากบางส่วนไม่ได้ การค้นหาเว็บเกี่ยวกับข้อ จำกัด ดังกล่าวอาจเป็นเรื่องยากเนื่องจากคำศัพท์แตกต่างกันไป คำว่าคีย์หลักแบบผสมควรจำเป็น;)

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



2

การใช้คีย์หลักในหลายตารางมีประโยชน์เมื่อคุณใช้ตารางกลางในฐานข้อมูลเชิงสัมพันธ์

ฉันจะใช้ฐานข้อมูลที่ฉันเคยสร้างเป็นตัวอย่างและโดยเฉพาะสามตารางในตารางนั้น ฉันสร้างฐานข้อมูลสำหรับเว็บคอมมิคเมื่อหลายปีก่อน ตารางหนึ่งเรียกว่า "การ์ตูน" - รายชื่อการ์ตูนทั้งหมดชื่อเรื่องชื่อไฟล์ภาพ ฯลฯ คีย์หลักคือ "comicnum"

ตารางที่สองคือ "อักขระ" - ชื่อและคำอธิบายสั้น ๆ คีย์หลักอยู่ที่ "charname"

เนื่องจากการ์ตูนแต่ละเรื่องมีข้อยกเว้นบางตัวมีตัวละครหลายตัวและตัวละครแต่ละตัวปรากฏในการ์ตูนหลายเรื่องจึงเป็นไปไม่ได้ที่จะใส่คอลัมน์ใน "ตัวละคร" หรือ "การ์ตูน" เพื่อสะท้อนถึงสิ่งนั้น แต่ฉันสร้างตารางที่สามเรียกว่า "comicchars" และนั่นคือรายชื่อของตัวละครที่ปรากฏในการ์ตูนเรื่องใด เนื่องจากตารางนี้รวมสองตารางเป็นหลักจึงจำเป็นต้องมี แต่สองคอลัมน์: charname และ comicnum และคีย์หลักอยู่ในทั้งสอง


1

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

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

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