Tôi nên sử dụng nhiều khóa chính của cột hay thêm một cột mới?


15

Thiết kế cơ sở dữ liệu hiện tại của tôi sử dụng khóa chính nhiều cột để sử dụng dữ liệu hiện có (dù sao đó cũng là duy nhất) thay vì tạo một cột bổ sung gán cho mỗi mục nhập một khóa tùy ý. Tôi biết rằng điều này được cho phép, nhưng đã tự hỏi nếu đây là một thực hành mà tôi có thể muốn sử dụng một cách thận trọng và có thể tránh (giống như goto trong C).

Vì vậy, một số nhược điểm tôi có thể thấy trong cách tiếp cận này hoặc lý do tôi có thể muốn một khóa cột duy nhất là gì?


2
Tôi không biết, tôi nghĩ rằng điều này sẽ tốt hơn trên SO.
Thất vọngWithFormsDesigner

2
@FrustratedWithFormsDesigner Nó có thể chuyển sang SO, nhưng tôi nghĩ nó cũng hoạt động ở đây, vì trọng tâm của câu hỏi dường như là "ưu và nhược điểm của phương pháp này" chứ không phải là "tôi làm X như thế nào?".
Adam Lear

@Anna Lear ♦: Đó là "ưu và nhược điểm" về các quyết định thiết kế sẽ có tác động trực tiếp và chắc chắn đến tiền mã hóa, vì vậy tôi nghĩ SO sẽ là một nơi tốt hơn.
Thất vọngWithFormsDesigner

Câu trả lời:


8

Thông thường khi bạn có một bảng có khóa chính nhiều cột, đó là kết quả của một bảng tham gia (nhiều-nhiều) được nâng lên thành thực thể của chính nó (và do đó xứng đáng là khóa chính của chính nó). Có nhiều người sẽ tranh luận rằng bất kỳ bảng tham gia nào NÊN mặc định là một thực thể, nhưng đó là một cuộc thảo luận cho một ngày khác.

Chúng ta hãy xem xét một giả thuyết nhiều đến nhiều mối quan hệ:

Học sinh * --- * Lớp

(Một sinh viên có thể ở nhiều lớp, một lớp có thể có nhiều sinh viên).

Ở giữa hai bảng đó sẽ là một bảng nối được gọi là StudentClass (hoặc ClassStudent tùy thuộc vào cách bạn viết nó). Đôi khi, bạn muốn theo dõi những thứ như khi học sinh ở trong lớp. Vì vậy, bạn sẽ thêm nó vào bảng StudentClass. Tại thời điểm này, StudentClass đã trở thành một thực thể duy nhất ... và nên được đặt tên để nhận ra nó như vậy, ví dụ như Ghi danh.

Học sinh 1 --- * Ghi danh * --- 1 Lớp

(một học sinh có thể có nhiều Ghi danh, mỗi Ghi danh dành cho một lớp (hoặc đi ngược lại một Lớp có thể có nhiều Ghi danh, mỗi Ghi danh dành cho một Học sinh).

Bây giờ bạn có thể truy vấn những thứ như, có bao nhiêu học sinh đã đăng ký vào lớp Hóa học 101 trong năm qua? Hay những lớp học mà John Doe đã đăng ký khi theo học tại Đại học Acme? Điều này là có thể nếu không có khóa chính riêng biệt, nhưng một khi bạn có khóa chính để đăng ký, một truy vấn dễ dàng hơn sẽ là những lần đăng ký này (theo id), có bao nhiêu học sinh nhận được điểm qua?

Việc xác định xem một thực thể có xứng đáng với PK hay không để biết bạn sẽ thực hiện bao nhiêu truy vấn (hoặc thao tác) cho thực thể đó. Ví dụ, bạn muốn đính kèm các bài tập đã hoàn thành cho một học sinh trong lớp. Vị trí hợp lý để đính kèm thực thể này (Bài tập) sẽ là trên thực thể Ghi danh. Cho phép ghi danh, khóa chính của nó sẽ làm cho các truy vấn Chuyển nhượng đơn giản hơn.


1
Vì vậy, bạn sẽ thêm nó vào bảng StudentClass. Tại thời điểm này, StudentClass đã trở thành một thực thể duy nhất ... và nên được đặt tên để nhận ra nó như vậy, ví dụ như Ghi danh. Đó là một điều đơn giản, nhưng có rất nhiều giá trị trong việc này!
Botis

8

Nó có ý nghĩa có một cột id riêng biệt. Khi bạn muốn lấy một cái gì đó từ bảng cơ sở dữ liệu của mình, việc thực hiện sẽ dễ dàng hơn:

SELECT whatever FROM table WHERE id=13

hơn CHỌN bất cứ điều gì TỪ bảng WHERE col1 = 'val1' AND col2 = 'val2' AND col3 = 'val3'

Ví dụ: trong một ứng dụng web, nó chuyển thành một url trông như thế này:

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

hoặc như thế này:

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

4
Và việc thêm một bảng có liên quan sẽ dễ dàng hơn nhiều khi bạn có thể liên kết trên một Id, thay vì một số cột
CaffGeek

3
Xin lỗi, tại thời điểm này tôi phải -1, vì A) nó không phải là màu đen và trắng. Thêm một cột ID đi kèm với các tiêu cực như nơi và khi nào bạn tạo ID mới đó. Ngoài ra, nó có thể dẫn đến tham gia thêm hoặc SELECTtruy vấn. Và, B) , tôi không biết làm thế nào điều này thực sự gây ra bất kỳ loại yêu cầu URL nào (trừ khi bạn đang làm việc với một khung công tác xấu). Các URL của tôi không có bất kỳ chuỗi truy vấn nào ?id=13trong đó, hãy để một mình ?col1=val1&col2=val2&col3=val3.
Nicole

2
@renesis: Trang web này có các câu hỏi và người dùng duy nhất, nằm trong các URL. Mặc dù, đây là một phần của trường hợp đặc biệt, vì dữ liệu cụ thể đó không thay đổi.
Michael K

1
@Renesis, hầu hết (có lẽ là tất cả) các db hiện đại đều có các kiểu cột số nguyên auto_increment có thể tạo ID một cách tự động và an toàn và báo cáo lại chúng thông qua truy vấn sql hoặc lệnh gọi hàm thư viện. Hoặc trong một môi trường phân tán, bạn sử dụng hàm băm ngẫu nhiên lớn. Một số DB thậm chí sẽ tạo một cột id ẩn cho bạn nếu bạn chưa có cái nào trong bảng.
GrandmasterB

@Michael - Tôi không nói ID không bao giờ có trong URL. Tất nhiên họ. Nếu bạn có URL đại diện cho một hàng dữ liệu, thì vâng, dữ liệu đó có thể phải có một ID duy nhất. Trừ khi một số phần khác của URL đã cung cấp các phần khác của đa khóa. @GrandmasterB Cả hai công ty cuối cùng tôi đã làm việc (hơn 6 năm), cả hai đều sử dụng MySQL (một cũng hỗ trợ Oracle và SQL Server) đều có thể sử dụng tự động gia tăng, cũng không phải là một hàm băm ngẫu nhiên lớn.
Nicole

8

Về cơ bản, bạn đang hỏi liệu bạn nên sử dụng khóa thay thế hay khóa tự nhiên (trong trường hợp của bạn, nó nghe giống như khóa tự nhiên tổng hợp ). Đây là một bài viết tuyệt vời: http://www.agiledata.org/essays/keys.html

Tôi thích thay thế các khóa vì chúng đơn giản hóa việc quản trị trong vòng đời của DB (bạn không bao giờ phải lo lắng về việc hàm ý thay đổi ý nghĩa, điều này không bao giờ xảy ra nhưng trong bất kỳ hệ thống thực nào có con người tham gia). Tuy nhiên , nếu có rất nhiều các bảng "tra cứu" trong DB (tức là bảng mà về cơ bản chính: cặp giá trị), sau đó phím thay thế có thể nhận được rườm rà bởi vì bạn phải tham gia vào những bảng vào truy vấn để có được kết quả có ý nghĩa.

Ví dụ: giả sử bạn có hai thực thể: Địa chỉ và Quốc gia.

  • Mối quan hệ là: Địa chỉ * ----- 1 Quốc gia
  • Thực thể Quốc gia về cơ bản là một cặp khóa: giá trị (ví dụ: Hoa Kỳ: Hoa Kỳ, CA: Canada, MX: Mexico, v.v.)
  • Để truy vấn cấu trúc này cho tất cả các Địa chỉ tại Hoa Kỳ:

select * from Address where CountryCode = 'US'

  • Để thực hiện cùng một truy vấn với các khóa thay thế:

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

Tôi cảm thấy thoải mái khi bắt buộc các khóa tự nhiên cho các bảng tra cứu và thay thế các khóa cho mọi thứ khác, nếu tôi khá chắc chắn rằng các khóa tự nhiên sẽ không thay đổi quá thường xuyên, nếu có bao giờ.


5

Nó phụ thuộc vào cách bạn truy cập dữ liệu. Nếu bạn thực hiện nhiều tra cứu khóa một phần (trong đó bạn chọn bản ghi chỉ dựa trên hai trong số ba khóa) thì bạn sẽ muốn giữ các khóa đa phần. OTOH, nếu bạn có nhiều mối quan hệ 1: 1 với các bảng khác, có lẽ sẽ có ý nghĩa hơn khi có khóa thay thế.


1

Tôi muốn luôn có một khóa chính thay thế cho mỗi bảng. Nhưng không có nhiều lý do "khó" để thực thi điều này mà tôi đã nghe.

Lần duy nhất tôi từng có một khóa tự nhiên nhiều cột cắn tôi là với ORM. Thỉnh thoảng tôi sẽ gặp vấn đề với khóa chính nhiều cột bằng cách sử dụng Linq To Entities.


1

Không bao giờ nói không bao giờ, nhưng tham gia vào 4 cột là một nỗi đau. Bạn càng có nhiều cột với dữ liệu thông minh, cơ hội những giá trị đó có thể thay đổi càng cao. Cơ sở dữ liệu có thể được thiết lập để duy trì tính toàn vẹn tham chiếu với các bản cập nhật xếp tầng.

Bạn luôn có thể tạo một chỉ mục khác để xử lý các giá trị duy nhất.

Hiệu suất có thể không đáng kể trong hầu hết các trường hợp, nhưng bạn có thể kiểm tra các truy vấn của mình có và không có khóa thừa.


0

Tôi thấy thật khó để đưa ra một lý do chính đáng để ủy thác một khóa riêng, nhưng như bạn đã nói rất nhiều người đưa nó vào.

Tôi không tìm thấy sự trợ giúp này (đặc biệt là với bộ lưu trữ) khi xử lý các bảng thực tế / chi tiết. Canonical ví dụ một bảng thực tế bán hàng với một (customer_key, store_key, product_key) với số lượng không có ý nghĩa gì để có khóa cấp độ bản ghi.


0

Có PK là một số tự động int làm giảm rắc rối nếu bạn thấy rằng khóa tổng hợp của bạn trong thực tế có thể có các bản sao.


0

Có một cuộc thảo luận tốt từ năm 2002 về Ask Tom . Đó là đặc thù của Oracle, nhưng cuộc thảo luận rộng hơn có liên quan đến bất kỳ cơ sở dữ liệu nào bạn đang sử dụng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.