Giáo viên t-sql của tôi nói với chúng tôi rằng việc đặt tên cột "Id" của chúng tôi được coi là thực hành xấu mà không có bất kỳ giải thích nào thêm.
Tại sao việc đặt tên cột PK "Id" được coi là thông lệ xấu?
Giáo viên t-sql của tôi nói với chúng tôi rằng việc đặt tên cột "Id" của chúng tôi được coi là thực hành xấu mà không có bất kỳ giải thích nào thêm.
Tại sao việc đặt tên cột PK "Id" được coi là thông lệ xấu?
Câu trả lời:
Tôi sẽ đi ra và nói rằng: Nó không thực sự là một thực hành tồi (và ngay cả khi nó là, nó không phải là xấu).
Bạn có thể đưa ra đối số (như Chad đã chỉ ra) rằng nó có thể che dấu các lỗi như trong truy vấn sau:
SELECT *
FROM cars car
JOIN manufacturer mfg
ON mfg.Id = car.ManufacturerId
JOIN models mod
ON mod.Id = car.ModelId
JOIN colors col
ON mfg.Id = car.ColorId
nhưng điều này có thể dễ dàng được giảm thiểu bằng cách không sử dụng các bí danh nhỏ cho tên bảng của bạn:
SELECT *
FROM cars
JOIN manufacturer
ON manufacturer.Id = cars.ManufacturerId
JOIN models
ON models.Id = cars.ModelId
JOIN colors
ON manufacturer.Id = cars.ColorId
Việc thực hành LUÔN LUÔN sử dụng 3 chữ viết tắt đối với tôi có vẻ tồi tệ hơn nhiều so với sử dụng tên cột id
. (Trường hợp cụ thể: ai thực sự sẽ viết tắt tên bảng cars
bằng chữ viết tắt car
? Cái kết thúc đó phục vụ cho cái gì?)
Quan điểm là: nhất quán. Nếu công ty của bạn sử dụng Id và bạn thường mắc lỗi ở trên, thì hãy tập thói quen sử dụng tên bảng đầy đủ. Nếu công ty của bạn cấm cột Id, hãy sải bước và sử dụng bất kỳ quy ước đặt tên nào họ thích.
Tập trung vào việc học những thứ THỰC SỰ THỰC SỰ (chẳng hạn như nhiều truy vấn phụ tương quan lồng nhau) thay vì nghiên cứu các vấn đề như thế này. Vấn đề đặt tên cột của bạn là "ID" gần như là một vấn đề của hương vị hơn là một thực tiễn xấu.
LƯU Ý CHO NGƯỜI CHỈNH SỬA: Lỗi trong truy vấn này là cố ý và đang được sử dụng để tạo điểm. Xin vui lòng đọc câu trả lời đầy đủ trước khi chỉnh sửa.
cars
-> car
. Cảm ơn Chúa - bạn đã lưu ngón tay của tôi). Đừng đọc quá sâu vào nó.
cars
và manufacturer
. Một là số nhiều, cái còn lại thì không. Nếu mọi người muốn chọn tại db, đó là cách thực hành tồi nên được chọn.
Bởi vì khi bạn có một bảng có khóa ngoại, bạn không thể đặt tên khóa đó là "Id". Bạn có tên bảng là TableId
Và sau đó tham gia của bạn trông giống như
SELECT * FROM cars c JOIN manufacturer m ON m.Id = c.ManufacturerId
Và lý tưởng, điều kiện của bạn nên có cùng tên trường ở mỗi bên
SELECT * FROM cars c JOIN manufacturer m ON m.ManufacturerId = c.ManufacturerId
Vì vậy, mặc dù việc đặt tên Id là Nhà sản xuất có vẻ không cần thiết, nhưng điều đó khiến bạn ít có lỗi trong các điều kiện tham gia của mình vì các lỗi trở nên rõ ràng.
Điều này có vẻ đơn giản, nhưng khi bạn tham gia một vài bảng, nhiều khả năng bạn sẽ mắc lỗi, hãy tìm bảng bên dưới ...
SELECT *
FROM cars car
JOIN manufacturer mfg
ON mfg.Id = car.ManufacturerId
JOIN models mod
ON mod.Id = car.ModelId
JOIN colors col
ON mfg.Id = car.ColorId
Trong khi với cách đặt tên thích hợp, lỗi sẽ xuất hiện ...
SELECT *
FROM cars car
JOIN manufacturer mfg
ON mfg.ManufacturerId = car.ManufacturerId
JOIN models mod
ON mod.ModelId = car.ModelId
JOIN colors col
ON mfg.ManufacturerId = car.ColorId
Một lý do khác để đặt tên cho Id là "xấu" là khi bạn truy vấn thông tin từ một số bảng, bạn sẽ cần đổi tên các cột Id để bạn có thể phân biệt chúng.
SELECT manufacturer.Id as 'ManufacturerId'
,cars.Id as 'CarId'
--etc
FROM cars
JOIN manufacturer
ON manufacturer.Id = cars.Id
Với tên chính xác, đây không phải là một vấn đề
SELECT * FROM cars c JOIN manufacturer m ON manufacturer.Id = c.ManufacturerId
. Tôi đã sử dụng id
trong nhiều năm và không bao giờ tìm thấy những gì bạn mô tả là một vấn đề thực sự.
SELECT manufacturer.id FROM ...
. Mọi khó khăn do id
có thể được khắc phục rất dễ dàng, làm cho nó đơn giản chỉ là vấn đề của hương vị.
Thư viện ActiveRecord của Ruby và GORM của Groovi sử dụng "id" cho khóa thay thế theo mặc định. Tôi thích thực hành này. Sao chép tên bảng trong mỗi tên cột là dư thừa, tẻ nhạt để viết và tẻ nhạt hơn để đọc.
Các tên cột phổ biến hoặc chính như "Tên" hoặc "Id" phải được thêm tiền tố với Tên bảng.
Nó loại bỏ sự mơ hồ, dễ dàng tìm kiếm hơn, có nghĩa là bí danh cột ít hơn nhiều khi cần cả hai giá trị "Id".
Một cột ít được sử dụng hoặc kiểm toán hoặc không khóa (giả sử LastUpdatedDateTime) không thành vấn đề
name
và id
? Tại sao không có mỗi cột có tiền tố với tên bảng của nó? Có vẻ như tùy ý chọn hai tên đó để bắt buộc một tiền tố. Về mặt khái niệm, bạn phải có bảng để có ngữ cảnh của một cột. Tại sao không chỉ sử dụng tên bảng đó để làm rõ truy vấn: Person.Name, Animal.Name, Part.Name, ...
Chủ đề này đã chết, nhưng tôi muốn thêm rằng IMO không sử dụng Id
là một thực tiễn xấu. Các Id
cột là đặc biệt; đó là các khóa chính. Bất kỳ bảng nào cũng có thể có bất kỳ số lượng khóa ngoại, nhưng nó chỉ có thể có một khóa là chính. Trong cơ sở dữ liệu nơi tất cả các khóa chính được gọi Id
, ngay khi bạn nhìn vào bảng, bạn biết chính xác cột nào là khóa chính.
Hãy tin tôi, trong nhiều tháng nay tôi đã dành cả ngày mỗi ngày để làm việc trong rất nhiều cơ sở dữ liệu lớn (Salesforce) và điều tốt nhất tôi có thể nói về các lược đồ là mỗi bảng có một khóa chính được gọi Id
. Tôi có thể đảm bảo với bạn rằng tôi hoàn toàn không bao giờ bị nhầm lẫn về việc tham gia khóa chính với khóa ngoại vì PK được gọi Id
. Một điều khác mà mọi người không đề cập đến là các bảng có thể có những cái tên dài ngớ ngẩn như Table_ThatDoesGood_stuff__c
; Cái tên đó đủ tệ bởi vì kiến trúc sư đã nôn nao vào buổi sáng khi anh ta nghĩ đến cái bàn đó, nhưng bây giờ bạn đang nói với tôi rằng đó là cách thực hành không gọi khóa chính Table_ThatDoesGood_stuff__cId
(nhớ rằng tên cột SQL không phân biệt chữ hoa chữ thường).
Thành thật mà nói, vấn đề với hầu hết những người dạy lập trình máy tính là họ đã không viết một dòng mã sản xuất trong nhiều năm, và họ không biết một kỹ sư phần mềm làm việc thực sự làm gì. Đợi cho đến khi bạn bắt đầu làm việc và sau đó tự quyết định những gì bạn nghĩ có phải là một ý tưởng tốt hay không.
Tôi không coi đó là thực hành xấu. Kiên định là vua, như thường lệ.
Tôi nghĩ đó là tất cả về bối cảnh. Trong ngữ cảnh của bảng, "id" chỉ có nghĩa chính xác là những gì bạn mong đợi, một nhãn giúp xác định duy nhất nó với các bảng khác có thể giống (hoặc xuất hiện) giống hệt nhau.
Trong ngữ cảnh của các phép nối, bạn có trách nhiệm xây dựng các phép nối theo cách sao cho nó có thể đọc được cho bạn và nhóm của bạn. Cũng giống như có thể làm cho mọi thứ trở nên khó khăn với việc đặt cụm từ hoặc đặt tên kém, cũng có thể xây dựng một truy vấn có ý nghĩa với việc sử dụng hiệu quả các bí danh và thậm chí cả các bình luận.
Theo cùng một cách, một lớp Java có tên 'Foo' không có các thuộc tính của nó có tiền tố là 'Foo', không cảm thấy bắt buộc phải đặt tiền tố ID bảng của bạn bằng tên bảng. Nó thường rõ ràng trong bối cảnh ID được đề cập đến là gì.
BÙM, câu hỏi đã được trả lời.
Bây giờ hãy nói với giáo viên của bạn rằng SO thực hành thiết kế cơ sở dữ liệu xấu.
PostTypeId -> PostTypes.Id
; AcceptedAnswerId -> Answers.Id
; OwnerUserId -> Users.Id
. Tại sao một thực hành dễ dàng bị coi là 'xấu'?
Điều này khiến cho việc thực hiện một phép nối tự nhiên trên bàn trở nên khó khăn (và khó hiểu), thật tệ nếu không nói là rất tệ.
Natural Join là một tạo tác cổ xưa của SQL Lore (nghĩa là đại số quan hệ) mà bạn có thể đã thấy một trong những điều sau: trong một cuốn sách cơ sở dữ liệu có lẽ. Ý tôi là Natrual Join không phải là một ý tưởng SQL mới mẻ, mặc dù dường như phải mất mãi mãi để DBMS thực hiện nó, do đó, nó không phải là một ý tưởng mới để bạn thực hiện nó, thậm chí bạn có thể bỏ qua nó sự tồn tại của nó ngày nay.
Chà, nếu bạn đặt tên cho tất cả ID của khóa chính, thì bạn sẽ mất đi sự dễ dàng và đơn giản của phép nối tự nhiên. select * from dudes natural join cars
sẽ cần phải được viết select * from dudes inner join cars where cars.dudeid = dudes.id
hoặc select * from dudes inner join cars where dudes.carid = cars.id
. Nếu bạn có thể tham gia một cách tự nhiên, bạn có thể bỏ qua mối quan hệ thực sự là gì, mà theo tôi, là khá tuyệt vời.
Có một tình huống mà việc dán "ID" trên mỗi bảng không phải là ý tưởng tốt nhất: USING
từ khóa, nếu nó được hỗ trợ. Chúng tôi sử dụng nó thường xuyên trong MySQL.
Ví dụ: nếu bạn có fooTable
cột fooTableId
và barTable
khóa ngoại fooTableId
, thì các truy vấn của bạn có thể được xây dựng như sau:
SELECT fooTableId, fooField1, barField2 FROM fooTable INNER JOIN barTable USING (fooTableId)
Nó không chỉ tiết kiệm gõ, mà còn dễ đọc hơn nhiều so với cách thay thế:
SELECT fooTable.Id, fooField1, barField2 FROM fooTable INNER JOIN barTable ON (fooTable.Id = barTable.foTableId)
USING
từ khóa được hỗ trợ bởi cơ sở dữ liệu Postgres / mysql / sqlite, có nghĩa là ít gõ mà một số các danh sách câu trả lời khác như một lý do để sử dụng id
, và cuối cùng là theo ý kiến chủ quan của tôi là dễ đọc hơn.
Tại sao không chỉ hỏi giáo viên của bạn?
Hãy nghĩ về điều này, khi tất cả các cột PK trong bảng của bạn được đặt tên, ID
điều đó làm cho việc sử dụng chúng làm khóa ngoại là một cơn ác mộng.
Tên cột cần có ý nghĩa về mặt ngữ nghĩa. ID
là chung chung.
id
một mình không có nghĩa gì cả, đặc biệt là trong bối cảnh khóa ngoại sang bảng khác. Điều này không có gì để làm classes
và tất cả mọi thứ để làm với thiết kế cơ sở dữ liệu quan hệ cơ bản cơ bản tốt.
table.id
là một cách hoàn toàn chấp nhận được khi đề cập đến một id
lĩnh vực. Tiền tố tên trường với tên bảng là dư thừa.
ID xấu vì những lý do sau:
Nếu bạn thực hiện nhiều truy vấn báo cáo, bạn luôn phải đặt bí danh cho các cột nếu bạn muốn xem cả hai. Vì vậy, nó trở nên lãng phí thời gian khi bạn có thể đặt tên đúng cho nó để bắt đầu. Các truy vấn phức tạp này đủ khó (tôi viết các truy vấn có thể dài hàng trăm dòng) mà không phải chịu thêm gánh nặng khi thực hiện các công việc không cần thiết.
Nó có thể gây ra lỗi mã. Nếu bạn sử dụng cơ sở dữ liệu cho phép sử dụng phép nối tự nhiên (không phải tôi nghĩ bạn nên sử dụng cơ sở dữ liệu đó nhưng khi có tính năng thì sẽ có người sử dụng chúng), bạn sẽ tham gia sai nếu bạn nhận được một nhà phát triển sử dụng nó.
Nếu bạn đang sao chép các phép nối để tạo một truy vấn phức tạp, thật dễ dàng quên thay đổi bí danh thành một truy vấn bạn muốn và nhận được một phép nối không chính xác. Nếu mỗi id được đặt tên theo bảng, thì bạn sẽ thường gặp lỗi cú pháp. Cũng dễ dàng hơn để phát hiện nếu truy vấn phức tạp tham gia không chính xác nếu tên pPK và tên FK khớp.
ID
không thuyết phục tôi chút nào.
Có một số câu trả lời tiếp cận những gì tôi sẽ xem là lý do quan trọng nhất cho việc không sử dụng "id" làm tên cột cho khóa chính trong bảng: cụ thể là tính nhất quán và giảm sự mơ hồ.
Tuy nhiên, đối với tôi, lợi ích chính được nhận ra bởi lập trình viên bảo trì, đặc biệt là người không liên quan đến sự phát triển ban đầu. Nếu bạn đã sử dụng tên "PersonID" cho ID trong bảng Person và thường xuyên sử dụng tên đó làm khóa ngoại, việc viết một truy vấn đối với lược đồ để tìm ra bảng nào có PersonID mà không cần phải suy ra "PersonID" là tên được sử dụng khi nó là khóa ngoại. Hãy nhớ rằng, đúng hay sai, các mối quan hệ khóa ngoài không phải lúc nào cũng được thực thi trong tất cả các dự án.
Có một trường hợp cạnh trong đó một bảng có thể cần có hai khóa ngoại cho cùng một bảng, nhưng trong những trường hợp đó tôi sẽ đặt tên khóa gốc làm tên hậu tố cho cột, do đó, có thể dễ dàng tìm thấy ký tự đại diện,% PersonID những trường hợp đó là tốt.
Có, phần lớn điều này có thể được thực hiện bằng một tiêu chuẩn là có "id" và biết luôn luôn sử dụng nó như là "tên bảng", nhưng điều đó đòi hỏi cả hai phải biết rằng thực tiễn được áp dụng và phụ thuộc vào các nhà phát triển ban đầu để theo dõi với ít hơn thực hành tiêu chuẩn trực quan.
Trong khi một số người đã chỉ ra rằng nó đòi hỏi một số nét chính để viết ra các tên cột dài hơn, tôi sẽ khẳng định rằng việc viết mã chỉ là một phần nhỏ trong vòng đời hoạt động của chương trình. Nếu lưu tổ hợp phím nhà phát triển là mục tiêu, không bao giờ nên viết bình luận.
Là một người đã dành nhiều năm để duy trì các dự án lớn với hàng trăm bảng, tôi rất thích các tên nhất quán cho một khóa trên các bảng.
Companies
bảng có 2 khóa ngoại vào một Persons
bảng. Một đại diện cho Chủ tịch của công ty; người kia đại diện cho Thủ quỹ của công ty. Bạn thực sự sẽ gọi các cột PersonID1
và PersonID2
? Nó sẽ được mô tả nhiều hơn để gọi cho họ PresidentID
và TreasurerID
. Tôi thấy nó dễ đọc inner join Person AS Presidents ON Company.PresidentID = Presidents.ID
hơn nhiềuinner join Person AS Person1 ON Company.PersonID1 = Person1.PersonID
CompanyOfficer
hoặc CompanyPerson
bảng cho phép mối quan hệ nhiều-nhiều với giữa Company
và Person
với thông tin bổ sung về bản chất của mối quan hệ. Nếu tôi triển khai nó trong Company
bảng, tôi sẽ sử dụng tên cột PresidentPersonID
và TreasurerPersonID
để giữ phần * PersonID của tên trong khi thêm mô tả bổ sung. inner join Person as Presidents on Company.PresidentPersonID = Presidents.PersonID
Việc sử dụng Id làm trường khóa chính dẫn đến thực tiễn nơi id được thêm vào mỗi bảng. Rất nhiều bảng đã có thông tin duy nhất xác định duy nhất một bản ghi. Sử dụng THAT làm khóa chính và không phải là trường id bạn thêm vào mỗi bảng. Đó là một trong những nền tảng của cơ sở dữ liệu quan hệ.
Và đó là lý do tại sao sử dụng id là thông lệ xấu: id thường không phải là thông tin chỉ là tự động tăng.
xem xét các bảng sau:
PK id | Countryid | Countryname
1 | 840 | United States
2 | 528 | the Netherlands
Điều sai với bảng này là nó cho phép người dùng thêm một dòng khác: Hoa Kỳ, với mã quốc gia 840. Nó vừa phá vỡ tính toàn vẹn quan hệ. Tất nhiên, bạn có thể thực thi tính duy nhất trên các cột riêng lẻ hoặc bạn chỉ có thể sử dụng khóa chính đã có sẵn:
PK Countryid | Countryname
840 | United States
528 | the Netherlands
Bằng cách đó, bạn sử dụng thông tin bạn đã có làm khóa chính, là trung tâm của thiết kế cơ sở dữ liệu quan hệ.
Tôi không nghĩ rằng đó là một thực hành xấu nếu nó được sử dụng đúng cách. Thông thường có trường ID tự động tăng gọi là "ID" mà bạn không bao giờ phải chạm và sử dụng số nhận dạng thân thiện hơn cho ứng dụng. Nó có thể là một chút rườm rà để viết mã như thế from tableA a inner join tableB b on a.id = b.a_id
nhưng mã đó có thể được giấu đi.
Là một sở thích cá nhân, tôi có xu hướng tiền tố Id với tên của thực thể, nhưng tôi không thấy vấn đề thực sự khi chỉ sử dụng Id
nếu nó được xử lý hoàn toàn bởi cơ sở dữ liệu.
ID là đủ phổ biến, mà tôi không nghĩ rằng nó sẽ gây nhầm lẫn cho bất cứ ai. Bạn sẽ luôn muốn biết bảng. Đặt tên trường trong mã sản xuất mà không bao gồm bảng / bí danh là một thực tế xấu. Nếu bạn quá lo lắng về việc có thể nhanh chóng nhập các truy vấn đặc biệt, bạn sẽ tự mình thực hiện.
Chỉ hy vọng không ai phát triển cơ sở dữ liệu sql trong đó ID là một từ dành riêng.
CREATE TABLE CAR (ID);
Chăm sóc tên trường, khóa chính và tự động tăng thêm 1 bắt đầu bằng 1 tất cả trong một gói 2 ký tự nhỏ. Ồ, và tôi sẽ gọi nó là CARS nhưng nếu chúng ta sẽ tiết kiệm các nét chính và ai thực sự nghĩ rằng một bảng gọi là CAR sẽ chỉ có một?
Car
đại diện cho một Table
nơi mỗi Row
đại diện cho một Car
. Kêu gọi Cars
thay đổi ngữ nghĩa và cho thấy sự thiếu hiểu biết hoàn toàn về các nguyên tắc cơ bản của lý thuyết quan hệ chính thức. Rails là một ví dụ điển hình của một người biết đủ nguy hiểm .
Câu hỏi này đã bị đánh đập nhiều lần, nhưng tôi nghĩ rằng tôi cũng sẽ thêm ý kiến của mình.
Tôi sử dụng id có nghĩa là đó là định danh cho mỗi bảng, vì vậy khi tôi tham gia vào một bảng và tôi cần khóa chính, tôi sẽ tự động tham gia vào khóa chính.
Trường id là tự động, không dấu (có nghĩa là tôi không bao giờ phải đặt giá trị của nó và nó không thể âm)
Đối với khóa ngoại, tôi sử dụng tablenameid (lại là vấn đề về kiểu dáng), nhưng khóa chính tôi tham gia là trường id của bảng, vì vậy tính nhất quán có nghĩa là tôi luôn có thể kiểm tra các truy vấn dễ dàng
id cũng ngắn và ngọt ngào
Quy ước bổ sung - sử dụng chữ thường cho tất cả các tên bảng và cột, do đó không có vấn đề nào được tìm thấy do trường hợp
Một điều khác cần xem xét là nếu tên khóa chính khác với tên khóa ngoại, thì không thể sử dụng một số công cụ của bên thứ ba.
Ví dụ: bạn sẽ không thể tải lược đồ của mình vào một công cụ như Visio và để nó tạo ra ERD chính xác.
Tôi thấy mọi người ở đây bao gồm khá nhiều khía cạnh nhưng tôi muốn thêm rằng "id" không phải và không nên được đọc là "định danh" mà nó giống như một "chỉ mục" và chắc chắn nó không nêu hoặc mô tả danh tính của hàng. (Tôi có thể đã sử dụng từ ngữ sai ở đây, vui lòng sửa lại cho tôi nếu tôi đã làm)
Đó là ít nhiều cách mọi người đọc dữ liệu bảng và cách họ viết mã của họ. Cá nhân tôi và rất có thể đây là cách phổ biến nhất mà tôi thấy thường xuyên hơn là các lập trình viên viết toàn bộ tài liệu tham khảo table.id
, ngay cả khi họ không cần phải thực hiện liên kết hoặc / và tham gia. Ví dụ:
SELECT cars.color, cars.model FROM cars WHERE cars.id = <some_var>
Bằng cách đó, bạn có thể dịch nó sang tiếng Anh là "Hãy cho tôi màu sắc và kiểu dáng của chiếc xe được đánh số là". và không phải là "Hãy cho tôi màu sắc và kiểu xe của chiếc xe được xác định là số." ID không đại diện cho chiếc xe theo bất kỳ cách nào, đó chỉ là chỉ số của xe, một số sê-ri nếu bạn muốn. Giống như khi bạn muốn lấy phần tử thứ ba từ một mảng.
Vì vậy, để tóm tắt những gì tôi muốn thêm là đó chỉ là vấn đề ưu tiên và cách đọc mô tả SQL là phổ biến nhất.
Mặc dù, có một số trường hợp không được sử dụng, chẳng hạn như (một ví dụ hiếm gặp hơn nhiều) khi ID là một chuỗi thực sự mô tả. Ví dụ id = "RedFordMustang1970"
hoặc một cái gì đó tương tự. Tôi thực sự hy vọng tôi có thể giải thích điều này ít nhất để có được ý tưởng.