Quy ước đặt tên khóa chính / khóa ngoại [đóng]


95

Trong nhóm nhà phát triển của chúng tôi, chúng tôi có một cuộc tranh luận gay gắt liên quan đến quy ước đặt tên cho Khóa chính và Khóa ngoại. Về cơ bản có hai trường phái suy nghĩ trong nhóm của chúng tôi:

1:

Primary Table (Employee)   
Primary Key is called ID

Foreign table (Event)  
Foreign key is called EmployeeID

hoặc là

2:

Primary Table (Employee)  
Primary Key is called EmployeeID

Foreign table (Event)  
Foreign key is called EmployeeID

Tôi không muốn trùng lặp tên của bảng trong bất kỳ cột nào (Vì vậy, tôi thích tùy chọn 1 ở trên). Về mặt khái niệm, nó phù hợp với nhiều phương pháp được đề xuất trong các ngôn ngữ khác, nơi bạn không sử dụng tên của đối tượng trong tên thuộc tính của nó. Tôi nghĩ rằng việc đặt tên cho khóa ngoại EmployeeID(hoặc Employee_IDcó thể tốt hơn) sẽ cho người đọc biết rằng đó là IDcột của EmployeeBảng.

Một số người khác thích tùy chọn 2 trong đó bạn đặt tên khóa chính được đặt trước tên bảng để tên cột giống nhau trong toàn bộ cơ sở dữ liệu. Tôi hiểu điểm đó, nhưng bây giờ bạn không thể phân biệt một cách trực quan khóa chính với khóa ngoại.

Ngoài ra, tôi nghĩ rằng việc có tên bảng trong tên cột là thừa, bởi vì nếu bạn coi bảng là một thực thể và một cột là một thuộc tính hoặc thuộc tính của thực thể đó, bạn nghĩ nó là thuộc tính ID của Employee, không các EmployeeIDthuộc tính của một nhân viên. Tôi không đi một đồng nghiệp của tôi hỏi những gì mình PersonAgehoặc PersonGenderlà. Tôi hỏi anh ấy Tuổi của anh ấy là bao nhiêu.

Vì vậy, như tôi đã nói, đó là một cuộc tranh luận gay gắt và chúng tôi tiếp tục lặp đi lặp lại về nó. Tôi muốn có một số quan điểm mới.


1
câu hỏi trùng lặp this stackoverflow.com/questions/208580/…
Mike Henke

1
Tôi đã đọc hơn 10 câu hỏi tương tự và cuối cùng tìm thấy 3 câu trả lời hàng đầu ở đây rất tốt: stackoverflow.com/a/465146/781695
người dùng

Chỉ là một lưu ý phụ: Lựa chọn 2 sẽ cho phép bạn 'Tham gia tự nhiên'. Heck, tại sao vẫn không làm điều đó ở lựa chọn 1 bằng cách thêm 'Employee.ID làm EmployeeID'. Nhưng cách thực hành tốt hơn dường như là 'Tham gia' bằng cách sử dụng 'ON Employee.ID = Event.EpriseeID'.
Leo

Trong cả hai trường hợp, bạn sẽ phải sử dụng bí danh (hoặc 'table_name.column_name') trong một hoặc nhiều hàng đợi bởi vì bạn, trong cả hai trường hợp đều lặp lại tên cột.
Please_Dont_Bully_Me_SO_Lords

Câu trả lời:


52

Nó không thực sự quan trọng. Tôi chưa bao giờ gặp phải một hệ thống có sự khác biệt thực sự giữa lựa chọn 1 và lựa chọn 2.

Jeff Atwood đã có một bài viết rất hay về chủ đề này. Về cơ bản, mọi người tranh luận và tranh luận dữ dội nhất về những chủ đề mà họ không thể được chứng minh là sai. Hoặc từ một góc độ khác, những chủ đề chỉ có thể giành được chiến thắng thông qua các lập luận dựa trên độ bền kiểu phim truyền hình.

Chọn một và yêu cầu họ tập trung vào các vấn đề thực sự ảnh hưởng đến mã của bạn.

CHỈNH SỬA: Nếu bạn muốn giải trí, hãy yêu cầu họ chỉ rõ lý do tại sao phương pháp của họ ưu việt hơn đối với các tham chiếu bảng đệ quy.


26
+1, cho cảm giác chung ... Có những điều quan trọng hơn để tranh luận về .. Vì vậy, làm theo cách của tôi (lựa chọn 2)
Charles Bretana

5
Và, đối với DRI tự tham chiếu, khi có nhiều hơn một FK tự tham chiếu cùng một PK, bạn PHẢI vi phạm cả hai "tiêu chuẩn", vì hai cột FK không thể được đặt tên giống nhau ... ví dụ: EmployeeTable với EmployeeId PK, SupervisorId FK, MentorId Fk, PartnerId FK, v.v.
Charles Bretana.

75

Nếu hai cột có cùng tên trong cả hai bảng (quy ước # 2), bạn có thể sử dụng cú pháp USING trong SQL để tiết kiệm một số thao tác nhập và một số tiếng ồn từ bảng soạn sẵn:

SELECT name, address, amount
  FROM employees JOIN payroll USING (employee_id)

Một lập luận khác ủng hộ quy ước số 2 là đó là cách mô hình quan hệ được thiết kế.

Ý nghĩa của mỗi cột được truyền đạt một phần bằng cách gắn nhãn nó với tên miền tương ứng.


4
Cú pháp và ngữ nghĩa của SQL thực sự cung cấp một manh mối khá tốt về cách nó nên được sử dụng. ví dụ: cú pháp USING có nghĩa là các cột có cùng tên miền nên có cùng tên, NULL = NULL -> NULL nghĩa là NULL là "không xác định" chứ không phải "không áp dụng" và ON UPDATE CASCADE nghĩa là các khóa chỉ cần là duy nhất, không phải bất biến.
Steven Huwig

6
Thậm chí tốt hơn, nó cho phép này: SELECT name, address, amount FROM employees NATURAL JOIN payroll.
ngày

5
Tôi không sử dụng tham gia tự nhiên trong mã đã triển khai, vì nó dễ hơn trong trường hợp bổ sung lược đồ. Nhưng đối với truy vấn tương tác, điều đó thật tuyệt.
Steven Huwig

3
+1 nhưng luôn có một ngoại lệ. Ví dụ: nếu bạn có hai cột trong bảng lương đều là khóa ngoại đối với nhân viên (ví dụ: một tham chiếu đến người đang được trả lương, cột thứ hai cho người quản lý có thẩm quyền về ngân sách, chẳng hạn). Nhưng chúng tôi không thể đặt tên cho cả hai khóa ngoại employee_id.
Bill Karwin

1
Từ khóa "using" là dành riêng cho MySql. Không hoạt động trong T-SQL — rất tiếc.
birdus

12

Tôi nghĩ rằng nó phụ thuộc vào cách ứng dụng của bạn được kết hợp với nhau. Nếu bạn sử dụng ORM hoặc thiết kế bảng của mình để đại diện cho các đối tượng thì tùy chọn 1 có thể dành cho bạn.

Tôi thích viết mã cơ sở dữ liệu dưới dạng lớp riêng của nó. Tôi kiểm soát mọi thứ và ứng dụng chỉ gọi các thủ tục được lưu trữ. Thật tuyệt khi có tập kết quả với tên cột hoàn chỉnh, đặc biệt khi có nhiều bảng được nối và nhiều cột được trả về. Với kiểu ứng dụng này, tôi thích tùy chọn 2. Tôi thực sự thích thấy tên cột khớp trên các phép nối. Tôi đã làm việc trên các hệ thống cũ mà chúng không khớp và đó là một cơn ác mộng,


4
+1 vì phải tìm ra các liên kết có tên cột không khớp
Raj More

4
trên "hệ thống cũ", điểm chấp của tên dài 8 ký tự gây đau đớn hơn thế này rất nhiều. Tôi sẵn sàng bỏ ra ngoài và suy đoán rằng việc PK có tên ID không phải là nguyên nhân chính gây ra cơn ác mộng trong các hệ thống cũ mà bạn đang xử lý. Ngoài ra "nó bị hút trong các hệ thống cũ" được sử dụng waaaaay quá thường xuyên trong phát triển phần mềm, đặc biệt là cơ sở dữ liệu. Tôi thường thấy mọi người biện minh cho bất kỳ phương pháp A nhất định nào, dựa trên cách nó hoạt động theo kinh nghiệm của họ trên hệ thống DB được phát hành hơn 10 năm trước.
Russell Steen

2
hiện nay nhà nước của nghệ thuật ứng dụng sẽ là tào lao cũ trong một vài năm. bạn thậm chí có thể viết lại giao diện hoặc sử dụng dữ liệu trong một nền tảng khác, nhưng dữ liệu của bạn (bao gồm cả tên cột của bạn) sẽ cần phải có thời gian.
KM.

2
Vì vậy, con người cách đây 20 năm lẽ ra bằng cách nào đó đã sử dụng tên cột có ý nghĩa như ngày nay, mặc dù chúng chỉ có 8 ký tự? Các định dạng lưu trữ dữ liệu đã thay đổi mạnh mẽ trong 20 năm qua và sẽ thay đổi lại trong 20 năm tới. Không có cách nào để chứng minh rằng sở thích của bạn sẽ chịu đựng được thử thách của thời gian tốt hơn các phương pháp khác được liệt kê. "tên cột" có thể đã "cũ" vào thời điểm mọi người đang thảo luận về vấn đề này sau 20 năm nữa, khi khả năng lưu trữ và thao tác dữ liệu của chúng ta được cải thiện. Bàn là một cấu trúc con người không hoàn hảo đại diện cho quan hệ dữ liệu ...
Russell Steen

1
Cảm ơn bạn đã phản hồi trí tuệ hợp lý.
Russell Steen 10/09/09

3

Không quy ước nào hoạt động trong mọi trường hợp, vậy tại sao lại có một quy ước nào đó? Sử dụng suy nghĩ thông thường...

ví dụ: đối với bảng tự tham chiếu, khi có nhiều hơn một cột FK tự tham chiếu đến PK của cùng một bảng, bạn phải vi phạm cả hai "tiêu chuẩn", vì hai cột FK không thể được đặt tên giống nhau ... ví dụ: , EmployeeTable với EmployeeId PK, SupervisorId FK, MentorId Fk, PartnerId FK, ...


1
+1 cho câu trả lời về mục tiêu kỹ thuật thực tế
DVK

Một câu trả lời hay, có thể áp dụng được, nhưng lập luận cho câu trả lời của Dems không chính xác.
JYelton

3

Tôi đồng ý rằng có rất ít sự lựa chọn giữa chúng. Đối với tôi, một điều quan trọng hơn nhiều về một trong hai tiêu chuẩn là phần "tiêu chuẩn".

Nếu mọi người bắt đầu 'làm việc riêng của họ', họ sẽ bị căng thẳng bởi những người khác. IMHO :)


3
1 công nhận nhất quán đó là quan trọng hơn là "đúng" (trong trường hợp này)
Russell Steen

-1 vì cố gắng áp dụng "nhất quán ngu ngốc". Câu ngạn ngữ cổ của Trung Quốc nói rằng "Sự kiên định ngu ngốc là một hobgoblin cho những tâm hồn đơn giản."
Charles Bretana

@charles: trong một thế giới mà những người khác nhau duy trì mã cho nhau, thường là khi người viết đã rời đi và tài liệu đã lỗi thời hoặc không tồn tại, đây không phải là sự nhất quán ngu ngốc. Tôi rất vui vì tôi không làm việc với Bạn ...
MatBailie

@Dems, không có ý định xúc phạm, nhưng điều này là ngu ngốc, vì hai lý do. 1) Có những tình huống phổ biến, được hiểu rõ ràng mà BẤT KỲ tiêu chuẩn nào sẽ PHẢI bị vi phạm. (xem câu trả lời của tôi cho ví dụ và 2) vì về vấn đề này, ít nhất, một tiêu chuẩn sẽ làm tăng thêm rất ít giá trị, ngoại trừ việc làm cho folks người như tiêu chuẩn cảm thấy thoải mái hơn ...
Charles Bretana

1
bạn có thể tranh luận "ID" nhất quán hơn - bởi vì ngay sau khi bạn giới thiệu ngôn ngữ tiếng Anh "carID" trong bảng "ô tô" hoặc bảng "ô tô"? "Cừu" trong bảng "cừu" hoặc "những con cừu" - mọi thứ bắt đầu trở nên mâu thuẫn. Nếu bạn dính vào "ID" và tên bảng số ít - điều này không chỉ nhất quán mà còn chơi tốt với nhiều ORM / cũng yêu cầu cấu hình ít hơn (ví dụ: Dapper Contrib)
niico

3

Bạn đã xem xét những điều sau đây chưa?

Primary Table (Employee)   
Primary Key is PK_Employee

Foreign table (Event)  
Foreign key is called FK_Employee

3
Tôi không thể chịu đựng được khi mọi người bỏ phiếu và không nêu lý do tại sao. Đây là một câu trả lời hoàn toàn hợp lệ, liệu nó có hợp khẩu vị với một số người hay không là một câu hỏi khác, nhưng đó là chủ quan và không cần thiết phải bỏ phiếu thuận.
Jeremy

1
Cảm ơn vì đã chỉ ra điều này. Tôi cũng muốn biết lý do tại sao bạn không sử dụng định dạng này. Và tôi khá chắc chắn sẽ có lý do chính đáng ...
Wouter

Đây là cách tốt nhất vì bạn sẽ không phải sử dụng table_name.column_nametrong các truy vấn và sẽ không phải sử dụng bí danh cho tên cột nếu không có tên lặp lại ...
Please_Dont_Bully_Me_SO_Lords

1
Đây có thể được coi là một dạng ký hiệu Hungary. Vì vậy, hãy xem xét các lập luận ủng hộ và chống lại điều đó.
Fred

2

Quy ước mà chúng tôi sử dụng ở nơi tôi làm việc khá gần với A, ngoại trừ việc chúng tôi đặt tên bảng ở dạng số nhiều (tức là "nhân viên") và sử dụng dấu gạch dưới giữa tên bảng và cột. Lợi ích của nó là để tham chiếu đến một cột, đó là "nhân viên _ id" hoặc "nhân viên.id", tùy thuộc vào cách bạn muốn truy cập nó. Nếu bạn cần chỉ định bảng đến từ cột nào, thì "worker.employees _ id" chắc chắn là thừa.


Tôi chưa quyết định xem mình có thích tên bảng số nhiều hay không. Bằng cách sử dụng số ít, các truy vấn dường như đọc tốt hơn ("worker.name" thay vì "staff.name"). Ngay cả trong các phép nối, nó có vẻ đọc tốt hơn khi bạn đang nối các bản ghi đơn lẻ vào một bảng khác. Nhưng tên bảng số nhiều có vẻ chính xác hơn khi nghĩ về bảng, thay vì truy vấn. Sẽ gắn bó với số ít như đó là những gì chúng tôi sử dụng, nhưng tôi nghĩ rằng nó cũng là cách đúng đắn để đi (mặc dù một lần nữa, nhiều không đồng ý)
MatBailie

Vâng. Tôi đoán đó là sở thích cá nhân và / hoặc bất cứ thứ gì bạn thường thấy.
Jarett Millard

2

Nếu bạn đang xem mã ứng dụng, không chỉ truy vấn cơ sở dữ liệu, một số điều có vẻ rõ ràng với tôi:

  1. Các định nghĩa bảng thường ánh xạ trực tiếp đến một lớp mô tả một đối tượng, vì vậy chúng phải là số ít. Để mô tả một bộ sưu tập của một đối tượng, tôi thường thêm "Mảng" hoặc "Danh sách" hoặc "Bộ sưu tập" vào tên số ít, vì nó rõ ràng hơn việc sử dụng số nhiều không chỉ cho biết đó là một bộ sưu tập mà còn là loại tập hợp nào. nó là. Trong dạng xem đó, tôi thấy tên bảng không phải là tên của tập hợp, mà là tên của loại đối tượng mà nó là một tập hợp. Một DBA không viết mã ứng dụng có thể bỏ lỡ điểm này.

  2. Dữ liệu tôi xử lý thường sử dụng "ID" cho các mục đích nhận dạng không quan trọng. Để loại bỏ sự nhầm lẫn giữa khóa "ID" và "ID" không phải khóa, đối với tên khóa chính, chúng tôi sử dụng "Khóa" (đó là cái gì phải không?) Có tiền tố là tên bảng hoặc chữ viết tắt của tên bảng. Tiền tố này (và tôi chỉ dành tiền tố này cho khóa chính) làm cho tên khóa trở thành duy nhất, điều này đặc biệt quan trọng vì chúng tôi sử dụng tên biến giống với tên cột cơ sở dữ liệu và hầu hết các lớp đều có cha, được xác định bằng tên của khóa cha. Điều này cũng cần thiết để đảm bảo rằng nó không phải là một từ khóa dành riêng, chỉ riêng "Key". Để tạo điều kiện thuận lợi cho việc giữ các tên biến chính nhất quán và cung cấp cho các chương trình thực hiện các phép nối tự nhiên, khóa ngoại có cùng tên được sử dụng trong bảng mà chúng là khóa chính. Tôi đã nhiều lần gặp các chương trình hoạt động tốt hơn theo cách này bằng cách sử dụng các phép nối tự nhiên. Về điểm cuối cùng này, tôi thừa nhận một vấn đề với các bảng tự tham chiếu, mà tôi đã sử dụng. Trong trường hợp này, tôi sẽ thực hiện một ngoại lệ đối với quy tắc đặt tên khóa ngoại. Ví dụ: tôi sẽ sử dụng ManagerKey làm khóa ngoại trong bảng Nhân viên để trỏ đến một bản ghi khác trong bảng đó.


Nhiều trình ánh xạ quan hệ đối tượng (ORM) như Entity Framework cho phép bạn ánh xạ một bảng thành một lớp có tên khác. Điều này cho phép bạn có một lớp có tên "Người dùng" và một bảng có tên "Người dùng".
Fred

2

Tôi thích quy ước số 2 - khi nghiên cứu chủ đề này và tìm câu hỏi này trước khi đăng câu hỏi của riêng mình, tôi đã gặp phải vấn đề ở đó:

Tôi đang chọn * từ một bảng có nhiều cột và nối nó với một bảng thứ hai có số cột lớn tương tự. Cả hai bảng đều có cột "id" làm khóa chính và điều đó có nghĩa là tôi phải chọn cụ thể từng cột (theo như tôi biết) để làm cho hai giá trị đó là duy nhất trong kết quả, tức là:

SELECT table1.id AS parent_id, table2.id AS child_id

Mặc dù sử dụng ước # 2 có nghĩa là tôi vẫn sẽ có một số cột trong kết quả có cùng tên, bây giờ tôi có thể xác định đó id Tôi cần (cha mẹ hoặc con) và, như Steven Huwig đề nghị, những USINGđiều tuyên bố đơn giản hoá hơn nữa.


2
SELECT *dù sao cũng là điều không nên cho (hầu hết) các truy vấn sản xuất, vì vậy đó không phải là lý do để chọn tiêu chuẩn đặt tên.
P Daddy,

1
Không đồng ý: bạn có thể cung cấp liên kết tới lý do tại sao lại như vậy không? Tôi không thích ý tưởng phải duy trì tên của 80 cột trong truy vấn của mình.
JYelton

Không thể tìm thấy liên kết vào lúc này (khó có thể google cho "*"), nhưng tôi sẽ phác thảo những điểm cơ bản: (1) những thay đổi đối với (các) bảng có thể tác động tiêu cực đến ứng dụng của bạn, (2) có thể không tốt cho hiệu suất và (3) chỉ định rõ ràng dữ liệu bạn thực sự cần có thể làm cho mã của bạn dễ hiểu hơn. Những điểm này có thể mở rộng, và có những ngoại lệ (như tôi đã ám chỉ) nhưng điều đó không thích hợp ở đây. Nếu bạn đăng câu hỏi này như một câu hỏi mới, tôi (và những người khác) rất vui được giải thích thêm.
P Daddy

2
Tôi có thể làm điều đó. Tôi nhận ra lợi ích về hiệu suất, nhưng phải cân nhắc đầu tư thời gian khi chỉnh sửa mã. Tôi luôn tìm cách cải thiện sự tương tác giữa ứng dụng và cơ sở dữ liệu. Cảm ơn.
JYelton

1
Tôi không chắc chắn SELECT *là không cho hầu hết các truy vấn sản xuất. Nếu nó làm tăng đáng kể tốc độ phát triển của bạn và làm cho mã của bạn ngắn gọn và dễ đọc hơn nhiều - cho phép bạn tập trung vào những vấn đề quan trọng hơn - tại sao không SELECT *? Nó phụ thuộc rất nhiều vào hoàn cảnh của từng tình huống và là sự đánh đổi giữa nhiều yếu tố. Một quy tắc hiếm khi phù hợp với mọi thứ.
niico

2

Tôi đã luôn sử dụng userId như một PK trên một bảng và userId trên một bảng khác làm FK. Tôi đang suy nghĩ nghiêm túc về việc sử dụng userIdPKuserIdFK làm tên để xác định cái này với cái kia. Nó sẽ giúp tôi xác định PK và FK nhanh chóng khi nhìn vào bảng và có vẻ như nó sẽ xóa mã khi sử dụng PHP / SQL để truy cập dữ liệu khiến nó dễ hiểu hơn. Đặc biệt là khi người khác nhìn vào mã của tôi.


1

Tôi sử dụng quy ước số 2. Tôi đang làm việc với một mô hình dữ liệu kế thừa, nơi tôi không biết cái gì là viết tắt của một bảng nhất định. Tác hại của việc dài dòng là ở đâu?


1

Làm thế nào về việc đặt tên cho khóa ngoại

role_id

trong đó vai trò là vai trò mà thực thể được tham chiếu có liên quan đến bảng hiện tại. Điều này giải quyết vấn đề tham chiếu đệ quy và nhiều fks vào cùng một bảng.

Trong nhiều trường hợp sẽ giống với tên bảng được tham chiếu. Trong trường hợp này, nó giống hệt với một trong những đề xuất của bạn.

Trong mọi trường hợp, lập luận dài dòng là một ý tưởng tồi


0

"Vị trí trong" nhân viên INNER THAM GIA đơn hàng ON order.employee_id = worker.id "có cần thêm bằng cấp không?".

Không cần thêm bằng cấp vì bằng cấp mà tôi đã nói đến đã có sẵn.

"lý do mà người dùng doanh nghiệp đề cập đến ID đơn hàng hoặc ID nhân viên là để cung cấp ngữ cảnh, nhưng ở cấp độ dữ liệu, bạn đã có ngữ cảnh vì bạn đang tham chiếu đến bảng".

Cầu nguyện, cho tôi biết, nếu cột được đặt tên là 'ID', thì việc "tham chiếu [sic] đến bảng" được thực hiện chính xác như thế nào, trừ khi bằng cách xác định tham chiếu này cho cột ID chính xác theo cách tôi đã nói?

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.