Чому люди рекомендують не використовувати ім’я "Id" для стовпця особи?


68

Мене вчили не використовувати ім'я Idдля стовпчика ідентичності моїх таблиць, але останнім часом я просто використовую його завжди, тому що це просто, коротко і дуже описово щодо того, якими є дані насправді.

Я бачив, як люди пропонують префіксацію Idімені таблиці, але це, здається, зробить більше роботи для людини, яка пише SQL-запити (або програміста, якщо ви використовуєте ORM, як Entity Framework), особливо на довших назвах таблиць, таких як CustomerProductIdабоAgencyGroupAssignementId

Один сторонній постачальник, якого ми найняли, щоб створити щось для нас, насправді назвав усі їх стовпці особи, Identщоб уникнути використання Id. Спочатку я думав, що вони це зробили, тому що це Idбуло ключове слово, але коли я переглянув його, я виявив, що Idце не ключове слово в SQL Server 2005, саме це ми використовуємо.

То чому люди рекомендують не використовувати ім’я Idдля стовпця особи?

Редагувати: Щоб уточнити, я не запитую, яку конвенцію іменування використовувати, або аргументи використовувати одну конвенцію іменування над іншою. Я просто хочу знати, чому рекомендується не використовувати Idдля імені стовпця особи.

Я єдиний програміст, а не dba, і для мене база даних - це просто місце для зберігання моїх даних. Оскільки я зазвичай будую невеликі додатки і зазвичай використовую ORM для доступу до даних, загальне поле для поля ідентичності набагато простіше працювати. Я хочу знати, чого я пропускаю, роблячи це, і якщо є якісь справді вагомі причини, щоб я цього не робив.


10
BF битва тут уже: programmers.stackexchange.com/q/114728/5905 Кілька з нас (читайте: мене) всмокталися в неї ...
gbn

Чи дійсно існує таке правило проти використання "id" як імені стовпця особи? ActiveRecord, стандартний ORM для Ruby on Rails, робить це саме за домовленістю. ar.rubyonrails.org
200_успіх

1
@ 200_success На рівні бази даних, так. Це сайт бази даних, а не сайт ORM;)
JNK

2
Також спеціально для SQL Server див. Dba.stackexchange.com/questions/124655/… та, точніше, connect.microsoft.com/SQLServer/feedback/details/2178150
Aaron Bertrand

Відповіді:


46

Префікс назви таблиці має дуже вагомі причини.

Поміркуйте:

TableA (id int identity, stringdata varchar(max))

TableB (id int identity, stringdata varchar(max))

Ми хочемо DELETEз TableAзаписів, які існують в обох таблицях. Досить просто, ми просто зробимо INNER JOIN:

DELETE a
FROM 
  TableA A
INNER JOIN 
  TableB B
    ON b.id = B.id

.... і ми просто знищили все TableA. Ми ненавмисно порівняли ідентифікатор B із самим собою - кожен запис збігався, а кожен запис був видалений.

Якби поля були названі, TableAIdі TableBIdце було б неможливо ( Invalid field name TableAid in TableB).

Особисто я не маю жодних проблем з використанням імені idв таблиці, але це дійсно краща практика попереднього вступу до нього з назвою таблиці (або з ім'ям сутності, якби TableAлюди були, тоді PeopleIdтеж добре працювали), щоб уникнути випадкового порівняння з неправильним полем та видувом щось вгору.

Це також робить дуже очевидним, звідки беруться поля в довгих запитах з великою кількістю JOINs.


10
Так це в основному конвенція про іменування для захисту від помилок? Я б подумав, що використання, begin transactionі commit transactionце буде кращою практикою, ніж використання (imo) більш відвертої схеми іменування
Рейчел

13
@Rachel: це для 1. ясності 2. уникайте зайвих псевдонімів стовпців 3. дозволяйте ПРИЄДНАЙТЕСЬ..УСІЛЬНУВАННЯ 4. дратуйте мавп PHP, які працюють в окремих об'єктах, а не наборах
gbn

4
@Rachel Якщо ви не помітили помилки під час написання запиту, і безпосередньо перед тим, як його виконати, навряд чи ви його помітите перед тим, як зробити це. Цей матеріал трапляється, навіщо робити це більш імовірно?
Енді

7
@Andy Я завжди роблю a, SELECTщоб знайти свої записи, перш ніж запустити DELETE, і коли я запускаю оператор, я завжди переконуюсь, що кількість рядків - це те, що я очікую перед введенням.
Рейчел

5
@Rachel Приємно, що у тебе є щось, що працює для тебе. Чи можете ви змусити всіх це зробити?
Енді

36

Переважно, це не допускати, щоб сторонні ключі не стали величезним болем. Скажімо, у вас є дві таблиці: Customer and AddressAddress. Первинний ключ для обох - це стовпець з назвою id, який є ідентифікаційним (int) стовпцем.

Тепер вам потрібно мати посилання на ідентифікатор клієнта від CustomerAddress. Очевидно, ви не можете назвати ідентифікатор стовпця, тому ви переходите з customer_id.

Це призводить до пари питань. По-перше, ви повинні послідовно пам’ятати, коли потрібно викликати стовпець «id», а коли - як «customer_id». І якщо ви зіпсуєте це, це призводить до другої проблеми. Якщо у вас є великий запит із десятком або близько того, і він не повертає жодних даних, веселіться, граючи, де Вальдо і шукає цей друкарський помилок:

ON c.id = ca.id

Ну, мав би бути ON c.id = ca.customer_id. Або ще краще, називайте свої стовпці особи описово, щоб це було ON c.customer_id = ca.customer_id. Тоді якщо ви випадково десь використовуєте неправильний псевдонім таблиці, customer_id не буде стовпцем у цій таблиці, і ви отримаєте приємну помилку компіляції, а не порожні результати та подальше присідання коду.

Зрозуміло, є випадки, коли це не допомагає, наприклад, якщо вам потрібно кілька зв'язків зовнішніх ключів від однієї таблиці до іншої однієї таблиці, але іменування всіх первинних ключів "id" теж не допомагає.


27

Ось короткий опис усіх відповідей щодо переваг, отриманих у конвенції щодо використання загальної назви для всіх первинних ключів:

  • Менше помилок, оскільки поля ідентичності не названі однаковими

    Ви не можете помилково написати запит, який приєднується B.Id = B.Idзамість A.Id = B.Id, тому що поля ідентичності ніколи не будуть названі точно такими ж.

  • Чіткіші назви стовпців.

    Якщо ви подивитеся на стовпчик з назвою CustomerId, ви відразу знаєте, які дані є в цьому стовпці. Якщо назва стовпця було чимось загальним Id, то вам потрібно знати назву таблиці, а також знати, які дані містить стовпець.

  • Уникайте зайвих псевдонімів стовпців

    Тепер ви можете написати SELECT CustomerId, ProductIdна підставі запиту , який з'єднується Customersз Products, замістьSELECT Customer.Id as CustomerId, Products.Id as ProductId

  • Дозволяє JOIN..USINGсинтаксис

    Ви можете з'єднати таблиці Customer JOIN Products USING (CustomerId)замість синтаксисуCustomer JOIN Products ON Customer.Id = Products.Id

  • Ключ простіше знайти в пошуку

    Якщо ви шукаєте поле особистості клієнта у великому рішенні, пошук CustomerIdнабагато корисніший, ніж пошукId

Якщо ви можете придумати будь-які інші переваги цієї конвенції про іменування, дайте мені знати, і я додам її до списку.

Чи вирішите ви використовувати унікальні або однакові імена стовпців для полів ідентичності, залежить від вас, але незалежно від того, що ви вибрали, будь ласка, будьте послідовні :)


12

Щоб скопіювати мою відповідь із пов'язаного питання:

Існує ситуація, коли наклеювати "ID" на кожну таблицю - не найкраща ідея: USINGключове слово, якщо воно підтримується. Ми часто використовуємо його в MySQL.

Наприклад, якщо у вас є fooTableстовпець fooTableIdта barTableіноземний ключ fooTableId, то ваші запити можуть бути побудовані як такі:

SELECT fooTableId, fooField1, barField2 FROM fooTable INNER JOIN barTable USING (fooTableId)

Це не лише економить набравши текст, але набагато читає порівняно з альтернативою:

SELECT fooTable.Id, fooField1, barField2 FROM fooTable INNER JOIN barTable ON (fooTable.Id = barTable.foTableId)

9

Після нормалізації схеми бази даних для обмеження надмірності таблиці поділяються на менші таблиці з усталеними відносинами (одна до однієї, одна до багатьох, багато до багатьох). У процесі поодинокі поля в вихідній таблиці можуть відображатися в декількох нормалізованих таблицях.

Наприклад, база даних для блогу може виглядати так у ненормалізованому вигляді, передбачаючи унікальне обмеження на прізвище автора.

| Author_Nickname | Author_Email | Post_Title | Post_Body |
+-----------------+--------------+------------+-----------+
| dave            | dave@x.com   | Blah       | Bla bla   |
| dave            | dave@x.com   | Stuff      | I like    |
| sophie          | s@oph.ie     | Lorem      | Ipsum     |

Нормалізуючи це, виведете дві таблиці:

Автор:

| Author_Nickname | Author_Email |
+-----------------+--------------+
| dave            | dave@x.com   |
| sophie          | s@oph.ie     |

Опублікувати

| Author_Nickname | Post_Title | Post_Body |
+-----------------+------------+-----------+
| dave            | Blah       | Bla bla   |
| dave            | Stuff      | I like    |
| sophie          | Lorem      | Ipsum     |

Тут Author_Nickname буде первинним ключем для таблиці авторів, а зовнішнім ключем у таблиці публікацій. Навіть якщо Author_Nickname з'являється у двох таблицях, воно все одно відповідає одній одиниці інформації, тобто. кожній назві стовпця відповідає одне поле .

У багатьох випадках не може бути єдиного обмеження на вихідні поля, тому натомість основним ключем використовується числове штучне поле. Це не змінює той факт, що назва кожного стовпця все ще являє собою одне поле. У традиційному дизайні бази даних назви окремих стовпців відповідають окремим полям, навіть якщо вони не є ключами. (наприклад, використовуватимете part.partname та client.clientname, а не part.name та client.name ). Це причина існування з INNER JOIN ... USING <key>і NATURAL JOINсинтаксисів.

Однак сьогодні і з шарами ORM, доступними багатьма мовами, бази даних часто розробляються як шар стійкості для мов OO, в якому природно, що змінні, які мають однакову роль у різних класах, називаються однаковими ( part.name та client.name , не part.partname та client.clientname ). У такому контексті я, як правило, використовую 'ID' для своїх первинних ключів.


7

Один сторонній постачальник, якого ми найняли, щоб створити щось для нас, насправді назвав усі свої стовпці ідентифікаторів Ident лише для того, щоб не використовувати Id.

Використання "Ident" замість "Id" насправді нічого не вирішує, якщо "Ident" в кінцевому підсумку використовується на всіх їхніх таблицях.

На сайті Drupal є хороша стаття про конвенції про кодування SQL, яка вказує на добру практику в цій ситуації:

Рекомендується префіксувати назви таблиць із назвою модуля, щоб запобігти можливим конфліктам у просторі імен.

З цієї точки зору, CustomerProductId та AgencyGroupAssignmentId мають сенс використовувати. Так, це досить багатослівно. Ви можете скоротити це, але найбільший момент, з яким потрібно потурбуватись, - чи зрозуміє, що ви мали на увазі розробник, який стежить за вами . Ідентифікатори, наперед назви багатослівних таблиць, не повинні залишати двозначності щодо того, що вони є. І це (для мене) важливіше, ніж зберегти кілька натискань клавіш.


7

Я називаю свої стовпці CustomerID замість ідентифікатора, тому щоразу, коли я набираю текст

FROM dbo.Customers AS c JOIN dbo.CustomerOrders AS o

Підказка SQL відразу пропонує наступне

ON c.CustomerID = o.CustomerID 

Це врятує мені кілька натискань клавіш. Але я вважаю, що називати конвенції дуже суб'єктивно, і як такий я не маю жодної сильної думки так чи інакше.


5

Це та сама причина, чому ви б не назвали всі ваші поля вархар чимось на кшталт "UserText" та "UserText1", або чому ви б не використовували "UserDate" та "UserDate1".

Зазвичай, якщо у таблиці є поле ідентичності, це ваш основний ключ. Як би ви створили дочірню таблицю із зовнішнім ключем до батьківської таблиці, якби основний ключ в обох таблицях був ідентифікатором?

Не всі згодні з цією методологією, але в своїх базах даних я призначаю кожну таблицю унікальної абревіатури. ПК для цієї таблиці буде називатися ідентифікатором PK_ [abbrv]. ЯКЩО це використовується як FK будь-де, тоді я б використовував ідентифікатор FK_ [abbrv]. Тепер у мене немає нульової здогадки щодо з'ясування того, які стосуються таблиці.


5

В основному з тієї ж причини ти зазвичай не називаєш параметри1, параметр2 ... це точно, але не є описовим. Якщо ви бачите TableId, то, ймовірно, можете з упевненістю припустити, що він використовується для зберігання pk для таблиці, незалежно від контексту.

Що стосується того, хто використовував Ident, він повністю пропускає точку, даючи вибір між Ident і Id-використанням Id. Ідентифікатор ще більш заплутаний, ніж Id.

Поза контекстом, Id можна вважати основним ключем до якоїсь таблиці (не надзвичайно корисно, якщо ідентифікатор не є настановою), але Ident навіть не каже вам (або принаймні мені) про це. Я врешті-решт зрозумів би, що Ident - це короткий ідентичність (так чи інакше), але час, який я витратив, з'ясовуючи це, буде марно витрачений.


3

Використовуйте префікс, щоб те саме ім’я можна було використовувати як у контекстах первинного ключа, так і в зовнішньому ключі, щоб ви могли виконувати natural join/ join ... using.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.