วิธีการสร้างคีย์หลักคอมโพสิตอย่างเหมาะสม - MYSQL


182

นี่คือตัวอย่างที่ชัดเจนของการตั้งค่าที่เข้มข้นที่ฉันกำลังทำงานด้วย table_1และtable_2ทั้งคู่มีคีย์หลักตัวแทนเพิ่มขึ้นอัตโนมัติเป็น ID infoเป็นตารางที่มีข้อมูลเกี่ยวกับทั้งสองและtable_1table_2

table_1 (id, field)  
table_2 (id, field, field)
info ( ???, field)

ฉันพยายามที่จะตัดสินใจว่าผมควรจะทำให้คีย์หลักของinfoคอมโพสิตของรหัสจากและtable_1 table_2ถ้าฉันจะทำสิ่งนี้สิ่งใดที่เหมาะสมที่สุด?
(ในตัวอย่างนี้ฉันรวม ID 11209 กับ ID 437)

INT(9)11209437 (ฉันจินตนาการได้ว่าทำไมสิ่งนี้ถึงไม่ดี)
VARCHAR (10) 11209-437
DECIMAL (10,4)11209.437

หรืออย่างอื่น?

นี่จะเป็นการดีถ้าใช้นี่เป็นคีย์หลักในฐานข้อมูล MySQL MYISAM?


เป็นไปได้ที่ซ้ำกันของคีย์หลักแบบหลายคอลัมน์ใน MySQL 5
dotancohen

คำตอบ:


344

ฉันจะใช้คีย์ผสม (หลายคอลัมน์)

CREATE TABLE INFO (
    t1ID INT,
    t2ID INT,
    PRIMARY KEY (t1ID, t2ID)
) 

วิธีนี้คุณสามารถมี t1ID และ t2ID เป็นปุ่มต่างประเทศที่ชี้ไปยังตารางที่เกี่ยวข้องได้เช่นกัน


2
โอ้ว้าวนั่นเป็นวิธีที่คุณสร้างคีย์ผสม! ดูเหมือนว่าฉันเข้าใจแนวคิดผิดไปหมดแล้ว ขอบคุณ!! ดังนั้นสิ่งนี้มีวัตถุประสงค์เพื่อจัดทำดัชนีทั้งหมดถูกต้องหรือไม่ ในขณะที่ฉันไม่สามารถอ้างอิงบันทึกโดยใช้คอมโพสิตนี้ฉันจะยังคงต้องทำเช่นนั้นUPDATE info ... WHERE t1ID=11209 AND t2ID=437?
ฆา

2
แก้ไข. แม้ว่าคอลัมน์ทั้งสองควรไม่ซ้ำกันโดยที่ t1ID = 11209 น่าจะเพียงพอ
AlexCuse

39
@AlexCuse การรวมกันของทั้งสองคอลัมน์นั้นไม่ซ้ำกัน แต่สำหรับ t1ID = 11209 อาจมี t2ID จำนวนเท่าใดก็ได้
e18r

21

ฉันจะไม่สร้างคีย์หลักของตาราง "info" เป็นการรวมกันของค่าสองค่าจากตารางอื่น

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

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


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

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

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

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

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

15

ไวยากรณ์เป็นCONSTRAINT constraint_name PRIMARY KEY(col1,col2,col3)ตัวอย่าง ::

CONSTRAINT pk_PersonID PRIMARY KEY (P_Id,LastName)

ตัวอย่างข้างต้นจะใช้งานได้หากคุณกำลัง writting มันในขณะที่คุณกำลังสร้างตารางเช่น ::

CREATE TABLE person (
   P_Id int ,
   ............,
   ............,
   CONSTRAINT pk_PersonID PRIMARY KEY (P_Id,LastName)
);

เพื่อเพิ่มข้อ จำกัด นี้ลงในตารางที่มีอยู่คุณต้องทำตามไวยากรณ์ต่อไปนี้

ALTER TABLE table_name ADD CONSTRAINT constraint_name PRIMARY KEY (P_Id,LastName)

8

สมมติว่าคุณได้สร้างตารางแล้วตอนนี้คุณสามารถใช้แบบสอบถามนี้เพื่อสร้างคีย์หลักแบบรวม

alter table employee add primary key(emp_id,emp_name);

5

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

ตัวอย่างเช่นแต่ละรัฐของสหรัฐฯมีเขตรัฐสภาที่ไม่เหมือนใคร ในขณะที่หลายรัฐอาจมี CD-5 เป็นรายบุคคล แต่จะไม่มีมากกว่าหนึ่ง CD-5 ใน 50 รัฐและในทางกลับกัน ดังนั้นการสร้างเขตข้อมูลอัตโนมัติสำหรับ Massachusetts CD-5 จะซ้ำซ้อน

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

ดังนั้นในขณะที่ฉันไม่ตอบคำถามดั้งเดิมฉันขอขอบคุณคำตอบโดยตรงของอดัม


4

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



1

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

ที่กล่าวว่า t1ID นั้นไม่เหมือนใครใน table_1 แต่นั่นก็ไม่ได้ทำให้เป็นเอกลักษณ์ในตาราง INFO เช่นกัน

ตัวอย่างเช่น:

Table_1มี:
รหัสฟิลด์
1 A
2 B

Table_2มี:
รหัสฟิลด์
1 X
2 Y

INFOสามารถมี:
t1ID ฟิลด์ t2ID
1 1 บาง
1 2 ข้อมูล
2 1 ในแต่ละ
แถว 2 2

ดังนั้นในตาราง INFO เพื่อระบุแถวที่ไม่ซ้ำกันคุณต้องมีทั้ง t1ID และ t2ID


คีย์คอมโพสิตที่เรียกว่า
Pavel P

1
@PavelP คำตอบของฉันคือความคิดเห็นของ wrt Alex "แม้ว่าเนื่องจากทั้งสองคอลัมน์ควรไม่ซ้ำกันโดยที่ t1ID = 11209 น่าจะเพียงพอ" ... ฉันยอมรับว่าการใช้คีย์คอมโพสิตนั้นถูกต้อง แต่เพื่อระบุการจับคู่ที่ตรงกันคุณจะต้องมีทั้ง t1ID และ t2ID ... ฉันหวังว่ามันชัดเจน
sactiw
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.