Mỗi bảng có một khóa chính thay thế một trường / nhân tạo không?


33

Tôi hiểu một lợi ích của khóa thay thế / khóa nhân tạo nói chung - chúng không thay đổi và điều đó có thể rất thuận tiện. Điều này đúng cho dù chúng là một lĩnh vực hay nhiều lĩnh vực - miễn là chúng là 'nhân tạo'.

Tuy nhiên, đôi khi dường như vấn đề chính sách là có trường số nguyên tăng tự động làm khóa chính của mỗi bảng. Đây có phải luôn là ý tưởng tốt nhất để có một khóa đơn trường như vậy không và tại sao (hoặc tại sao không)?

Để rõ ràng, câu hỏi này không phải là về nhân tạo so với tự nhiên - mà là về việc liệu tất cả các khóa nhân tạo có phải là một trường đơn không


Câu trả lời:


28

Tôi sẽ nói không, không phải lúc nào cũng vậy, nhưng hầu hết thời gian là có. .

Đây là một số trường hợp bạn không cần khóa thay thế hoặc khóa nhân tạo:

  • Bàn giao nhau thuần túy . Nếu không có rủi ro về giao lộ là mục tiêu của khóa ngoại và nếu có ít hoặc không có rủi ro về giao lộ thu hút các thuộc tính độc lập (nghĩa là một cái gì đó không phải là FK cho hai bảng cha) thì bạn có thể thoát khỏi bằng cách sử dụng kết hợp của FK là PK với sự tự tin công bằng.
  • Bảng tra cứu với các khóa nghiệp vụ tĩnh . Nếu bạn có một
    bảng tra cứu với khóa doanh nghiệp duy nhất được gắn bên ngoài cho
    doanh nghiệp của bạn và không có cơ hội thay đổi cho bất kỳ
    mục đích thực tế nào , thì sử dụng trực tiếp khóa doanh nghiệp có thể giúp
    mọi việc đơn giản hơn. Một ví dụ có thể là danh sách
    mã tiểu bang hoặc tỉnh hoặc danh sách các số chuẩn ANSI, v.v.
  • Các bảng chứa dữ liệu được hợp nhất từ ​​nhiều nguồn độc lập . Nếu hệ thống của bạn có nhiều nguồn dữ liệu phải được chia thành một bảng duy nhất, thì tại trụ sở chính, đôi khi bạn cần một khóa tổng hợp bao gồm giá trị khóa hệ thống nguồn và mã cho biết hệ thống nguồn là gì.

Cũng có một số tình huống mà khóa thay thế số nguyên tăng đơn điệu trung thành cũ không lý tưởng. Bạn có thể có các khóa được thay thế bằng chữ và số. Chúng có thể bao gồm:

  • Các tình huống mà bạn cần hợp nhất dữ liệu từ nhiều nguồn độc lập. Để tránh va chạm khóa, bạn có thể sử dụng GUID thay vì các phím IDENTITY.
  • Các tình huống trong đó bạn buộc phải sử dụng các biểu diễn khóa không phải là số. Giả sử bạn đã có một cơ sở dữ liệu biển số xe. Khóa của bạn có thể là giá trị chữ và số thay vì số thuần túy.
  • Các tình huống trong đó một số yêu cầu bên ngoài buộc bạn phải áp dụng nén cho giá trị chính của mình. Thay vì sử dụng 10 chữ số cho một int32, bạn có thể sử dụng sáu chữ số cơ bản 36.

Tại sao hầu hết thời gian có? Câu trả lời cơ bản nhất cho câu hỏi đó là địa ngục thuần túy nếu bạn cần sửa đổi một giá trị khóa chính trên bất kỳ bảng nào. Vì hầu hết mọi thứ mà người dùng có thể nhìn thấy hoặc chạm vào đều có thể hiểu được một bản cập nhật tại một số điểm, sử dụng giá trị khóa hiển thị đang mời gọi địa ngục thuần túy. Sử dụng khóa thay thế sẽ giúp bạn không rơi vào cái bẫy này.

Đã nói rằng, hãy nhớ rằng có chỗ cho YAGNI trong việc áp dụng khái niệm này. Bạn không cần phải buộc các bảng mã có khóa IDENTITY vào mọi ngóc ngách của lược đồ của mình, chỉ trong trường hợp ai đó quyết định rằng biểu tượng cho giới tính nam trong bảng nhân viên của bạn cần thay đổi từ M sang X hoặc một cái gì đó ngớ ngẩn.


"Sử dụng khóa thay thế sẽ giúp bạn không rơi vào cái bẫy này" Câu hỏi không phải là về thay thế so với tự nhiên, mà là về thay thế một trường so với đa trường.
Jack Douglas

Như bạn đã thừa nhận trong một nhận xét cho câu trả lời của riêng bạn, chúng tôi đang ở trong lãnh thổ "đồng ý không đồng ý" khi nói đến những gì cần thiết trong thiết kế cơ sở dữ liệu. Với chỉnh sửa của bạn, tôi sẽ không phân biệt giữa khóa thay thế và khóa tự nhiên, vì vậy, gạch đầu dòng thứ hai của tôi bị lạc đề. Những điểm khác của tôi liên quan đến khi người ta có thể chuyển hướng khỏi phương pháp tiếp cận danh tính / trình tự cổ điển vẫn đứng vững.
Joel Brown

Tôi đã không thay đổi câu hỏi như bạn có thể thấy trong lịch sử, chỉ nhấn mạnh vào đó tôi nghĩ nó sẽ giúp người đọc lướt qua
Jack Douglas

12

Không.

Tôi muốn nói rằng chắc chắn có trường hợp khi các khóa đơn trường kém hơn các phím ghép, ít nhất là cho mục đích của khóa ngoại . Điều đó không có nghĩa là bạn không nên có khóa thay thế một trường nếu bạn thích, nhưng cá nhân tôi thích khóa thường được sử dụng làm mục tiêu của khóa ngoại được gọi là khóa chính

Tôi sẽ cố gắng minh họa quan điểm của mình trong các ví dụ sau, trong đó:

  • brand là marque xe, ví dụ Ford, Toyota vv
  • dealer là đại lý vật lý, gắn liền với thương hiệu (ví dụ: đại lý Ford chỉ bán Fords)
  • model là loại xe như Ford Focus, Ford Fiesta v.v.
  • stock là số lượng xe forecourt hiện tại cho mỗi đại lý

Nếu chúng ta tạo khóa thay thế một trường cho dealermodelnhư sau:

create table brand( brand_id integer primary key );

create table dealer( dealer_id integer primary key, 
                     brand_id integer references brand )

create table model( model_id integer primary key, 
                    brand_id integer references brand )

create table stock( model_id integer references model, 
                    dealer_id integer references dealer, 
                    quantity integer,
                      primary key(model_id, dealer_id) )

sau đó có thể chèn một hàng vào stockliên kết Ford dealervới mô hình "Toyota". Thêm brand_id references brandvào stockchỉ làm cho vấn đề tồi tệ hơn. Mặt khác, nếu chúng ta giữ khóa ngoại như một phần của khóa chính như sau:

create table brand( brand_id integer primary key );

create table dealer( brand_id integer references brand, 
                     dealer_id integer, 
                       primary key(brand_id, dealer_id) )

create table model( brand_id integer references brand, 
                    model_id integer, 
                      primary key(brand_id, model_id) )

create table stock( brand_id integer, 
                    model_id integer, 
                    dealer_id integer, 
                    quantity integer,
                      primary key(brand_id, model_id, dealer_id),
                      foreign key(brand_id, model_id) references model,
                      foreign key(brand_id, dealer_id) references dealer )

bây giờ quy tắc rằng các đại lý "Ford" chỉ có thể dự trữ xe "Ford" được thực thi theo mô hình một cách tự nhiên.

Lưu ý rằng trong ví dụ 'khóa tổng hợp', dealer_idcó thể hoặc không thể là duy nhất, theo sở thích. Nó không cần phải là duy nhất (tức là một khóa thay thế), nhưng rất ít bị mất bằng cách làm cho nó trở nên như vậy (có lẽ là một ít không gian lưu trữ) và nó có thể rất tiện dụng vì vậy đó là cách tôi thường thiết lập, ví dụ:

create table dealer( brand_id integer references brand, 
                     dealer_id serial unique, 
                       primary key(brand_id, dealer_id) )

3
Làm các khoản phụ cấp cho các điều khoản thông thường về các ví dụ không nhất thiết phải hoàn hảo từ mọi góc độ, tôi sẽ nói rằng kiểu thiết kế này đặc biệt dễ vỡ. Mặc dù có điều gì đó thỏa mãn về việc tìm cách sử dụng DRI để thực thi các quy tắc kinh doanh, nó cũng lấy đi một số khả năng của bạn để đáp ứng với các thay đổi. Nếu Toyota mua Ford, hoặc ngay cả khi đại lý Ford quyết định bán một chiếc Toyota đã qua sử dụng, các quy tắc kinh doanh theo định hướng DRI của bạn sẽ khiến bạn phải đau đầu bảo trì.
Joel Brown

1
Vì vậy, "quy tắc kinh doanh của bạn có thể thay đổi". Điều đó đúng với bất kỳ quy tắc kinh doanh nào và luôn tiềm ẩn nhiều khó khăn để mô hình hóa lại. Tôi thường được cho biết các quy tắc kinh doanh là gì - tôi không tự quyết định chúng.
Jack Douglas

1
Bạn đang nói DRI hoàn toàn không nên được sử dụng để thực thi các quy tắc kinh doanh? Đó không phải là điều duy nhất DRI làm sao? - ngay cả các khóa ngoại đơn giản là các quy tắc kinh doanh được thi hành bởi DRI.
Jack Douglas

4
Tất nhiên DRI thực thi các quy tắc kinh doanh. Bạn phải quyết định quy tắc nào sẽ được thi hành theo mã và quy tắc nào trong lược đồ của bạn. Thay đổi lược đồ hầu như luôn luôn khó hơn thay đổi mã. Có hai loại quy tắc kinh doanh có thể đi vào mô hình dữ liệu của bạn. Một thuộc về đó và một không. Bản chất cơ bản của dữ liệu quan trọng đối với doanh nghiệp của bạn không thay đổi nhiều. Các cách cụ thể mà bạn vận hành trên dữ liệu đó có nhiều biến động . Một quy tắc như xe hơi có một nhà sản xuất thuộc mô hình dữ liệu. Một quy tắc như các đại lý sẽ không bao giờ bán hai thương hiệu xe hơi.
Joel Brown

4
"Thay đổi lược đồ hầu như luôn khó hơn thay đổi mã" IMO thì ngược lại. Trên thực tế tôi không đồng ý với hầu như tất cả những gì bạn vừa nói nhưng tôi nghi ngờ có bất kỳ điểm nào để tranh cãi về việc quăng với bạn, vì vậy tôi sẽ để nó ở đó.
Jack Douglas

12

"nó phụ thuộc"

Có: Các trường IDENTITY / AUTONUMBER thay thế là tốt khi khóa tự nhiên rộng và không phải là số. Lưu ý: điều này giả định sự kết hợp của "PK" và chỉ mục cụm xảy ra theo mặc định trong SQL Server và Sybase, v.v.

Không: nhiều / nhiều bảng khi 2 phím cha đủ. Hoặc khi khóa tự nhiên ngắn và có độ dài cố định, ví dụ mã tiền tệ

Tất nhiên, một ORM braindead (đọc: (n) Hibernate) có thể vượt qua các quy tắc này ...

Chỉnh sửa: đọc lại câu hỏi

Một bảng nhiều / nhiều với 2 khóa cha thay thế sẽ có PK nhiều cột.
Tuy nhiên, nó không cần một cột thay thế khác.

Nếu một bảng có khóa thay thế (IDENTITY, v.v.) thì nó không cần phải là nhiều cột.

Bạn có thể có một chìa khóa siêu bao gồm thay thế nhưng điều này sẽ được thực thi quy tắc khác (ví dụ như phân nhóm )

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.