Конвенція про іменування первинних ключів / іноземних [закрита]


95

У нашій групі розробників у нас бурхлива дискусія стосовно конвенції про іменування первинних та іноземних ключів. В нашій групі є дві школи думки:

1:

Primary Table (Employee)   
Primary Key is called ID

Foreign table (Event)  
Foreign key is called EmployeeID

або

2:

Primary Table (Employee)  
Primary Key is called EmployeeID

Foreign table (Event)  
Foreign key is called EmployeeID

Я вважаю за краще не дублювати назву таблиці в жодному з стовпців (тому я віддаю перевагу варіант 1 вище). Концептуально це відповідає багатьом рекомендованим практикам на інших мовах, де ви не використовуєте ім'я об'єкта у його назвах властивостей. Я думаю, що називання зовнішнього ключа EmployeeID(або, Employee_IDможливо, краще) говорить читачеві, що це IDстовпець Employeeтаблиці.

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

Крім того, я думаю, що зайвим є ім’я таблиці у назві стовпців, тому що якщо ви вважаєте таблицю сутністю, а стовпець - властивістю чи атрибутом цього об'єкта, ви вважаєте це атрибутом ID Employee, а не EmployeeIDатрибут працівника. Я не ходжу запитати мій товариш по службі , що його PersonAgeабо PersonGenderє. Я запитую його, який його вік.

Так, як я вже сказав, це бурхлива дискусія, і ми продовжуємо цю справу. Мені цікаво отримати нові перспективи.


1
питання дублює це stackoverflow.com/questions/208580/…
Майк Генке

1
Я прочитав більше 10 подібних питань і, нарешті, знайшов найкращі 3 відповіді тут хороші: stackoverflow.com/a/465146/781695
користувач

Лише бічна зауваження: вибір 2 дозволить вам "Приєднатися до природи". Чорт забирай, чому б досі не зробити це у виборі 1, додавши "Employee.ID як EmployeeID". Але кращим способом практики здається, що "приєднатися", використовуючи "ON Employee.ID = Event.E EmployeeeID".
Лев

В обох ситуаціях вам доведеться використовувати псевдонім (або 'table_name.column_name') в одному або декількох чергах, оскільки ви в обох випадках повторюєте імена стовпців.
Please_Dont_Bully_Me_SO_Lords

Відповіді:


52

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

Джефф Етвуд ще раз відзначив цю тему. В основному люди дискутують і найбільш люто сперечаються з тими темами, в яких вони не можуть бути доведені неправильно. Або з іншого боку, ті теми, які можна виграти лише завдяки витривалості у стилі філібустера, заснованої на стійких аргументах.

Виберіть його та скажіть їм, щоб зосередитися на проблемах, які насправді впливають на ваш код.

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


26
+1, для здорового глузду ... Є більш важливі речі, про які можна сперечатися .. Отже, зроби це по-моєму (вибір 2)
Чарльз Бретана

5
А для DRI, що самостійно посилається, коли є більше одного FK, який самостійно посилається на той самий ПК, ви повинні порушити обидва "стандарти", оскільки два стовпці FK не можуть бути названі однаковими ... наприклад, EmployeeTable з EmployeeId PK, SupervisorId FK, MentorId Fk, PartnerId FK, тощо, тощо ...
Чарльз Бретана

75

Якщо обидва стовпці мають однакове ім’я в обох таблицях (конвенція №2), ви можете використовувати синтаксис USING у SQL, щоб зберегти деякий набір тексту та деякий шум котла:

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

Ще один аргумент на користь конвенції №2 полягає в тому, що саме так була розроблена реляційна модель .

Значення кожного стовпця частково передається, позначаючи його іменем відповідного домену.


4
Синтаксис і семантика SQL насправді дають досить хорошу підказку щодо того, як його слід використовувати. напр. ВИКОРИСТАННЯ синтаксису означає, що стовпці з однаковим доменом повинні мати однакову назву, NULL = NULL -> NULL означає, що NULL є "невідомим", а не "не застосовується", а ON UPDATE CASCADE означає, що ключі мають бути лише унікальними, а не незмінними.
Стівен Ювіг

6
Ще краще, якщо вона дозволяє це: SELECT name, address, amount FROM employees NATURAL JOIN payroll.
одного дня, коли

5
Я б не використовував природне з'єднання у розгорнутому коді, оскільки він крихкіший у випадку доповнень до схем. Але для інтерактивних запитів це чудово.
Стівен Гувіг

3
+1, але завжди є виняток. Наприклад, якщо у вас є два стовпці в заробітній платі, які є обома іноземними ключами для працівника (одна посилання на особу, якій виплачують, другу - наприклад, менеджеру з бюджетних повноважень, наприклад). Але ми не можемо назвати обидва зовнішні ключі employee_id.
Білл Карвін

1
Ключове слово "використання" є специфічним для MySql. Не працює в T-SQL - на жаль.
birdus

12

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

Мені подобається кодувати базу даних як власний рівень. Я контролюю все, і додаток просто викликає збережені процедури. Приємно мати набори результатів із повними іменами стовпців, особливо коли багато об’єднаних таблиць і повернуто багато стовпців. З цим стилем застосування мені подобається варіант 2. Мені дуже подобається, щоб назви стовпців збігалися при приєднанні. Я працював над старими системами, де вони не відповідали, і це був кошмар,


4
+1 за те, що потрібно з’ясувати приєднання до невідповідних назв стовпців
Raj More

4
на "старих системах" гандикап з 8 символів довгих імен, що шкодить набагато більше, ніж це. Я готовий вийти на кінцівку і міркувати про те, що наявність ПК з ідентифікатором не було основною причиною кошмару у старих системах, з якими ви мали справу. Крім того, "це засмоктується в старих системах" використовується занадто часто в розробці програмного забезпечення, особливо в базах даних. Я звичайно бачу, як люди виправдовують будь-яку практику А, виходячи з того, як це працювало в їхньому досвіді в системі БД, випущеній 10+ років тому.
Рассел Стін

2
сьогоднішній сучасний рівень застосування вже через кілька років буде старою лайною . ви можете навіть переписати інтерфейс або використовувати дані на іншій платформі, але ваші дані (включаючи назви стовпців) потребують витримки часу.
КМ.

2
Тож люди 20 років тому повинні були якось використовувати назви стовпців, які мали сенс сьогодні, хоча вони мали лише 8 символів? За останні 20 років формати зберігання даних кардинально змінилися і знову змінитимуться протягом наступних 20. Немає способу продемонструвати, що ваші уподобання витримають тест часу краще, ніж інші перелічені методи. "Назви стовпців" самі по собі можуть бути "старим лаєм" до того часу, коли люди ведуть цю дискусію за 20 років, оскільки наша здатність зберігати та маніпулювати даними покращується. Таблиці - це людська конструкція, яка недосконало відображає відносини даних ...
Рассел Стін

1
Дякую за добре обґрунтовану інтелектуальну реакцію.
Рассел Стін

3

Жодна конвенція не діє у всіх випадках, тож навіщо її взагалі мати? Використовуйте здоровий глузд ...

наприклад, для таблиці з самопосиланням, коли є більше одного стовпця FK, який самостійно посилається на ПК однієї таблиці, ви повинні порушити обидва "стандарти", оскільки два стовпці FK не можуть бути названі однаковими ... наприклад , Таблиця співробітників з EmployeeId PK, SupervisorId FK, MentorId Fk, PartnerId FK, ...


1
+1 за фактичну технічну об’єктивну відповідь
DVK,

Хороша відповідна відповідь, але аргументи на відповідь Демса не відповідають суті.
JYelton,

3

Я згоден, що між ними мало що вибрати. Для мене набагато важливішою справою будь-якого стандарту є «стандартна» частина.

Якщо люди починають "робити власну справу", вони повинні бути нанизаними їх сітками. ІМХО :)


3
+1 за визнання того, що послідовність є важливішою, ніж бути "правильною" (в даному випадку)
Рассел Стін,

-1 за спробу застосувати "дурну консистенцію". Старе китайське прислів’я говорить: "Нерозумна консистенція - це хобгоблін для простих розумів".
Чарльз Бретана

@charles: у світі, де різні люди підтримують код один одного, часто, коли письменник пішов, а документація застаріла або не існує, це не дурна послідовність. Я такий радий, що не працюю з тобою ...
MatBailie

@ Деми, жодних злочинів не передбачалося, але це безглуздо з двох причин. 1) Існують загальні, чітко зрозумілі сценарії, коли БУДЬ будь-який стандарт мав би бути порушеним. (див. мою відповідь для прикладів та 2), оскільки, принаймні, у цьому питанні стандарт додав би дуже малої цінності, за винятком того, щоб люди, які люблять стандарти, почували себе комфортніше ...
Чарльз Бретана

1
Ви можете стверджувати, що "ID" є більш послідовним - адже як тільки ви вводите англійську мову "carID" в таблицю "автомобілі" або "автомобіль"? "ovaID" в таблиці "овець" або "вівці" - речі починають ставати непослідовними. Якщо ви дотримуєтесь "ID" та єдиних назв таблиці - це не лише послідовно, це добре грає з багатьма ORM / вимагає і меншої конфігурації (наприклад, Dapper Contrib)
niico

3

Чи розглядали ви наступне?

Primary Table (Employee)   
Primary Key is PK_Employee

Foreign table (Event)  
Foreign key is called FK_Employee

3
Я не можу витримати, коли люди проголосують і не ставлять причину. Це цілком коректна відповідь, чи це привабливо для деяких - це інше питання, але це суб'єктивно і не вимагає відмови.
Джеремі

1
Дякуємо, що вказали на це. Мені також були б цікаві причини, чому ви не використовуєте цей формат. І я цілком впевнений, що будуть вагомі причини ...
Воутер

Це найкращий вихід, оскільки вам не доведеться використовувати table_name.column_nameзапити і не потрібно використовувати псевдоніми для імен стовпців, якщо у вас немає повторених імен ...
Please_Dont_Bully_Me_SO_Lords

1
Це можна вважати формою угорського позначення. Тож розгляньте аргументи на користь і проти.
Фред

2

Конвенція, яку ми використовуємо там, де я працюю, досить близька до точки А, за винятком того, що ми називаємо таблиці у формі множини (тобто "службовці") і використовуємо підкреслення між таблицею та назвою стовпців. Вигода від цього полягає в тому, що для посилання на стовпець це або "співробітники _ ідентифікатор", або "службовці.id", залежно від способу доступу до нього. Якщо вам потрібно вказати, з якої таблиці надходить стовпець, "службовці.employees _ id", безумовно, зайві.


Я не вирішив, чи подобаються мені назви таблиць з плюралізом. Використовуючи однину, запити, здається, читаються краще ("ім'я співробітника" на відміну від "найменування співробітників"). Навіть під час приєднання, здається, він читається краще, коли ви приєднуєте окремі записи до іншої таблиці. Але множинні назви таблиць здаються точнішими, коли розмірковують про таблицю, а не про запит. Я буду дотримуватися однини, оскільки саме цим ми користуємось, але я думаю, що це також правильний шлях (хоча, знову ж таки, багато хто не згоден)
MatBailie

Так. Думаю, це більше особисті переваги та / або те, що ви звикли бачити.
Джаретт Міллард

2

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

  1. Визначення таблиці зазвичай безпосередньо відображаються в класі, який описує один об'єкт, тому вони повинні бути єдиними. Щоб описати колекцію об'єкта, я зазвичай додаю "Масив" або "Список" або "Колекція" до однини, оскільки це чіткіше, ніж використання множини, вказує не тільки на те, що це колекція, але і на яку колекцію Це є. У такому погляді я бачу назву таблиці не назвою колекції, а назвою типу об'єкта, яким вона є колекція. DBA, який не пише код програми, може пропустити цей пункт.

  2. Дані, з якими я маю справу, часто використовують "ідентифікатор" для неключових ідентифікаційних цілей. Для усунення плутанини між ключовими "ідентифікаторами" та нелюковими "ідентифікаторами", для імені первинного ключа ми використовуємо "Ключ" (ось що це, чи не так?) З префіксом назви таблиці або абревіатурою назва таблиці. Ця префіксація (і я зарезервую це лише для первинного ключа) робить ім'я ключа унікальним, що особливо важливо, оскільки ми використовуємо імена змінних, які є такими ж, як імена стовпців бази даних, і більшість класів мають батьківський, визначений іменем батьківський ключ. Це також потрібно, щоб переконатися, що це не зарезервоване ключове слово, яке є лише "Ключ". Щоб полегшити постійне узгодження імен ключових змінних та передбачити програми, які виконують природні з'єднання, іноземні ключі мають те саме ім’я, яке використовується в таблиці, в якій вони є первинним ключем. Я не раз стикався з програмами, які працюють набагато краще, використовуючи природні з'єднання. На цьому останньому моменті я визнаю проблему із таблицями самовідсилань, якими я користувався. У цьому випадку я б зробив виняток із правила іменування зовнішнього ключа. Наприклад, я б використовував ManagerKey як зовнішній ключ у таблиці Співробітник, щоб вказати на інший запис у цій таблиці.


Багато об’єктно-реляційних картографів (ORM), таких як Entity Framework, дозволяють зіставити таблицю з класом з іншим іменем. Це дозволяє мати клас під назвою "Користувач" та таблицю з назвою "Користувачі".
Фред

2

Мені подобається конвенція №2 - досліджуючи цю тему і знаходячи це питання, перш ніж розміщувати своє, я зіткнувся з проблемою, де:

Я вибираю * з таблиці з великою кількістю стовпців і приєдную його до другої таблиці, яка також має велику кількість стовпців. В обох таблицях стовпчик "id" в якості основного ключа, і це означає, що я повинен спеціально виділити кожен стовпець (наскільки я знаю), щоб зробити ці два значення унікальними в результаті, тобто:

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

Хоча використання умовного режиму №2 означає, що я все ще матиму кілька стовпців у результаті з тим самим іменем, тепер я можу вказати, який саме ідентифікатор мені потрібен (батько чи дитина), і, як запропонував Стівен Хьюїг, USINGзаява спрощує справи.


2
SELECT *У будь-якому разі це виробництво запитів (ні) для більшості виробників, тому це не є великою причиною для вибору стандарту іменування.
P тато

1
Не погоджуючись: чи можете ви надати посилання на причину, чому це так? Мені не подобається, що в моєму запиті потрібно підтримувати назви 80 стовпців.
JYelton

Наразі не вдається знайти посилання (важко перейти в Google для "*"), але я викладу основні моменти: (1) зміни таблиці (ів) можуть негативно вплинути на вашу програму, (2) це може бути погана продуктивність, і (3) чітко вказавши, які саме фактично потрібні вам дані можуть полегшити ваш код. Ці моменти можуть розширюватися, і є винятки (як я нагадав), але це не доречно. Якщо ви опублікуєте це як нове запитання, я (та інші) були б раді детальніше.
P тато

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

1
Я не так впевнений SELECT *, що немає для більшості виробничих запитів. Якщо це значно збільшує вашу швидкість розвитку і робить ваш код набагато більш лаконічним і читабельним - що дозволяє зосередитись на більш важливих питаннях - чому б і ні SELECT *? Це дуже залежить від обставин кожної ситуації і є компромісом між багатьма факторами. Одне правило рідко підходить усім.
niico

2

Я завжди використовував userId як ПК на одній таблиці, а userId на іншій таблиці - як FK. Я серйозно замислююся над тим, щоб використовувати userIdPK та userIdFK як імена для ідентифікації одного від іншого. Це допоможе мені швидко визначити PK та FK при перегляді таблиць, і, здається, він очистить код при використанні PHP / SQL для доступу до даних, що полегшує розуміння. Особливо, коли хтось інший дивиться на мій код.


1

Я використовую конвенцію №2. Я зараз працюю зі застарілою моделлю даних, де я не знаю, що означає дана таблиця. Де шкода бути багатослівним?


1

Як щодо називання зовнішнього ключа

role_id

де роль - це роль, на яку посилається суб'єкт господарювання, має відносну таблицю. Це вирішує питання про рекурсивну посилання та декілька fks до однієї таблиці.

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

У будь-якому випадку довгі аргументи Хавіна - це погана ідея


0

"Де в" співробітник INNER JOIN order ON ON order.employee_id = службовець.id ", чи є потреба в додатковій кваліфікації?".

Немає необхідності в додатковій кваліфікації, оскільки кваліфікація, про яку я говорив, уже є.

"причина, по якій бізнес-користувач посилається на ідентифікатор замовлення або ідентифікатор працівника, полягає у наданні контексту, але на рівні бази даних у вас вже є контекст, оскільки ви відповідаєте таблиці".

Помоліться, скажіть мені, якщо стовпець має ім'я "ID", то як саме виконується те "порівняння [sic] з таблицею", якщо тільки не кваліфікувати це посилання на стовпець ID точно так, як я говорив?

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