แต่ละตารางควรมีคีย์หลักหรือไม่


341

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

แต่ละตารางควรมีคีย์หลักหรือไม่


5
คุณช่วยให้รายละเอียดเพิ่มเติมเกี่ยวกับตาราง? คำตอบน่าจะเป็น "ใช่" แม้ว่า
Ryan Bair

7
ใช่แต่ละตารางควรมีคีย์หลัก
Syed Tayyab Ali

คำตอบ:


314

คำตอบสั้น: ใช่

คำตอบยาว:

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

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

โปรดทราบว่าคีย์หลักสามารถคอมโพสิต

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

นอกเหนือจากปัญหาความสอดคล้องเชิงตรรกะเอ็นจิ้น RDBMS ส่วนใหญ่จะได้รับประโยชน์จากการรวมฟิลด์เหล่านี้ไว้ในดัชนีที่ไม่ซ้ำกัน

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

ดูบทความนี้ในบล็อกของฉันสำหรับเหตุผลที่คุณควรสร้างดัชนีที่ไม่ซ้ำกับข้อมูลที่ไม่ซ้ำกัน:

ป.ล.มีบางกรณีที่พิเศษมากซึ่งคุณไม่ต้องการคีย์หลัก

ส่วนใหญ่จะรวมตารางบันทึกที่ไม่มีดัชนีใด ๆด้วยเหตุผลด้านประสิทธิภาพ


พวกเขายังคงมีคีย์หลักคอมโพสิตหนึ่ง
kristof

2
@annakata: พวกเขาควรจะมีคีย์หลักคอมโพสิต
Quassnoi

1
"และเนื่องจากคีย์หลักใด ๆ ที่เกี่ยวข้องกับการสร้างดัชนี UNIQUE" นั้นไม่เป็นความจริงสำหรับ Oracle หนึ่งสามารถใช้ดัชนีที่ไม่ซ้ำกันในการบังคับใช้คีย์หลัก ในความเป็นจริงบางครั้งจำเป็นต้องมีข้อ จำกัด ที่ไม่เหมือนใครและข้อ จำกัด PK ใช้ดัชนีที่ไม่ซ้ำกัน
สเตฟานีหน้า

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

1
กุญแจไม่ได้เกี่ยวข้องกับการเข้าร่วม และอาร์กิวเมนต์การจัดกลุ่มจะขึ้นอยู่กับ DBMS ที่คุณใช้และผสมการพิจารณาเชิงตรรกะและทางกายภาพ
Jon Heggland

36

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

ตามที่ระบุไว้โดยผู้อื่นมีเหตุผลบางอย่างที่จะไม่มีคีย์หลัก แต่ส่วนใหญ่จะไม่ได้รับอันตรายหากมีคีย์หลัก


5
@PaulSuart Data ไม่จำเป็นต้องอยู่ในรูปแบบปกติเสมอไป ในความเป็นจริงเมื่อข้อมูลมีขนาดใหญ่ก็ไม่ควรเก็บไว้ในรูปแบบปกติมิฉะนั้นการเข้าถึงข้อมูลจะทำให้ช้าลงอย่างน่ากลัวสำหรับแบบสอบถามที่ทำตารางร่วมกันเป็นต้นรูปแบบปกติเป็น "อุดมคติ" และเป็นไปได้ในทางปฏิบัติเท่านั้น ใหญ่
Pacerier

13

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


13
ตารางการเข้าร่วมเป็นคีย์หลัก - หนึ่งคอมโพสิตประกอบด้วย PK ของทั้งสองระเบียนที่เข้าร่วม เช่นสร้าง PersonOrder แบบตาราง (PersonId int, OrderId int, KEY หลัก (PersonId, OrderId))
Keith Williams

3
ใช่ แต่จะเกิดอะไรขึ้นถ้าตารางลิงก์มีแอตทริบิวต์ที่สามเช่นกันให้พูดว่า "OrderDate" คุณจะเพิ่มมันลงในคีย์ผสมหรือไม่ IMHO no - เพราะมันสามารถลดได้อีกและไม่ให้บริการ charactertic ที่ไม่สามารถหักล้างได้คีย์หลักควรมี
stevek

13

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

หากไม่มีคีย์หลักนั่นไม่ใช่ตาราง!

มาร์ค


10
การพูดประโยคนั้นผิด ตารางสามารถเป็น "ดูตาราง" ที่สร้างขึ้นโดยภาษาแบบสอบถามของคุณ RDBMS ประกอบด้วยความสัมพันธ์ไม่ใช่ตาราง ประโยคนั้นควรพูดว่า: "หากมันไม่มีคีย์หลักนั่นก็ไม่ใช่ความสัมพันธ์!"
stevek

หรือบางที "ถ้าไม่มีคีย์ตัวเลือกมันก็ไม่ใช่ตารางที่เกี่ยวข้อง" แต่ดูกรณีที่หายากมากซึ่งมันก็โอเคที่จะมีตารางที่ไม่ได้แสดงถึงความสัมพันธ์
Walter Mitty

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

1
ในตารางความสัมพันธ์แบบหลายต่อหลายคุณสามารถสร้างคีย์หลักแบบผสมซึ่งประกอบด้วยรหัสทั้งสองต่อความสัมพันธ์
Jaap

8

เพียงเพิ่มคุณจะต้องขออภัยในภายหลังเมื่อคุณไม่ได้ (การเลือกลบการเชื่อมโยง ฯลฯ )


8

คุณจะต้องเข้าร่วมตารางนี้กับตารางอื่น ๆ หรือไม่? คุณต้องการวิธีในการระบุบันทึกที่ไม่ซ้ำกันหรือไม่? หากคำตอบคือใช่คุณต้องมีคีย์หลัก สมมติว่าข้อมูลของคุณเป็นตารางลูกค้าที่มีชื่อของคนที่เป็นลูกค้า อาจไม่มีรหัสธรรมชาติเนื่องจากคุณต้องการที่อยู่อีเมลหมายเลขโทรศัพท์ ฯลฯ เพื่อตรวจสอบว่า Sally Smith นี้แตกต่างจาก Sally Smith หรือไม่และคุณจะเก็บข้อมูลนั้นไว้ในตารางที่เกี่ยวข้องเนื่องจากบุคคลนั้นสามารถมีโทรศัพท์ได้หลายอย่าง อีเมล ฯลฯ สมมติว่า Sally Smith แต่งงานกับ John Jones และกลายเป็น Sally Jones หากคุณไม่มีคีย์ปลอมบนตารางเมื่อคุณอัปเดตชื่อคุณเพิ่งเปลี่ยน 7 Sally Smiths เป็น Sally Jones แม้ว่าจะมีเพียงหนึ่งในพวกเขาแต่งงานและเปลี่ยนชื่อของเธอ

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

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


6

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

ตรวจสอบส่วนคีย์หลักและดัชนีแบบคลัสเตอร์บน Books Online (สำหรับ SQL Server)

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

แต่ตรวจสอบสิ่งนี้ด้วยเช่นกัน: http://www.aisintl.com/case/primary_and_foreign_key.html


1
ตรวจสอบสิ่งนี้ด้วยsql-server-performance.com/2006/primary-key-index-clustered
endo64

4
หน้านั้นค่อนข้างโง่ ก่อนอื่นต้องใช้คีย์หลักเพื่อเหตุผลด้านประสิทธิภาพ จากการอ่านหน้าของเขาฉันได้เรียนรู้ว่าการเพิ่ม ID ลงในตารางหนังสือนั้นไร้ประโยชน์เพราะข้อความของหนังสือนั้นไม่เหมือนใคร เห็นได้ชัดว่าคนที่แต่งตัวประหลาดไม่เคยทำงานกับฐานข้อมูล แต่เขาก็มีปัญหาในการทำความเข้าใจกับสิ่งที่เขาวิจารณ์ หน้าที่เขียนว่า 1) ค่า PK อ้างอิงแถว 2) คุณสามารถเข้าร่วม 2 ตารางโดยชุดของคอลัมน์ใด ๆ ไม่มีข้อขัดแย้ง มันวิเศษมากที่ผู้เขียนบทความทางวิชาการไม่เข้าใจพื้นฐานของทฤษฎีเชิงสัมพันธ์
Federico Razzoli

1
"ก่อนอื่นต้องใช้คีย์หลักเพื่อเหตุผลด้านประสิทธิภาพ" สิ่งนี้ไม่ถูกต้อง PK ไม่มีผลโดยตรงต่อประสิทธิภาพ การไม่มี PK อาจทำให้เกิดปัญหามากมาย (ระบุแถวเข้าร่วม ฯลฯ ) แต่ประสิทธิภาพไม่ใช่หนึ่งในนั้น เมื่อคุณสร้าง PK บนตาราง SQL เซิร์ฟเวอร์จะสร้างดัชนีที่ไม่ซ้ำกันในกลุ่มดัชนีนั้นจะมีผลต่อประสิทธิภาพไม่ใช่ตัว PK เอง ตามตัวอย่างจริงตารางของฉันมีดัชนีคลัสเตอร์ในคอลัมน์วันที่และ PK บนเขตข้อมูล GUID เนื่องจากแถวของฉันควรได้รับคำสั่งทางกายภาพมากกว่าคอลัมน์วันที่ในตารางเนื่องจากแบบสอบถามทั้งหมดมีช่วงวันที่ (ในกรณีของฉัน)
endo64

ดัชนีคลัสเตอร์นั้นเป็นรสชาติของคีย์หลักที่สร้างขึ้นโดย SQL Server และ DBMS อื่น ๆ คุณแน่ใจหรือไม่ว่าควรใช้มัน? ตัวอย่างเช่นใน MySQL ไม่ใช่เหตุผลที่ไม่มีเอกสารหลายประการ
Federico Razzoli

1
โปรดทราบว่า GUID ไม่ใช่ประเภทที่เหมาะสมที่สุดสำหรับ PKs ใน InnoDB ดัชนีทั้งหมดมีการอ้างอิงถึง PK ดังนั้นยิ่งใหญ่กว่าคือ PK ยิ่งใหญ่กว่าจะเป็นดัชนีอื่นทั้งหมด
Federico Razzoli

6

ไม่เห็นด้วยกับคำตอบที่แนะนำ คำตอบสั้น ๆ คือ: NO

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

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

ตัวอย่างเล็ก ๆ : ตาราง A: LogData

Columns:  DateAndTime, UserId, AttribA, AttribB, AttribC etc...

ไม่ต้องการคีย์หลัก

ตาราง B: ผู้ใช้

Columns: Id, FirstName, LastName etc. 

ต้องการคีย์หลัก (Id) เพื่อใช้เป็น "foreign key" ในตาราง LogData


3

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


3

เพื่อให้เป็นหลักฐานในอนาคตคุณควรทำ หากคุณต้องการทำซ้ำคุณจะต้องมี หากคุณต้องการที่จะเข้าร่วมในตารางอื่นในชีวิตของคุณ (และคนโง่ที่ต้องรักษาในปีหน้า) จะง่ายขึ้นมาก


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

3

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


2

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


1

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


1

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

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