Соглашение об именах первичного / внешнего ключа [закрыто]

97

В нашей группе разработчиков ведутся бурные дебаты по поводу соглашения об именах для первичных и внешних ключей. В нашей группе есть две основные точки зрения:

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, где вы называете первичный ключ с префиксом имени таблицы, чтобы имя столбца было одинаковым во всей базе данных. Я это понимаю, но теперь вы не можете визуально отличить первичный ключ от внешнего.

Кроме того, я считаю излишним иметь имя таблицы в имени столбца, потому что, если вы думаете о таблице как о сущности, а столбец как о свойстве или атрибуте этой сущности, вы думаете об этом как об атрибуте идентификатора 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.EmployeeID».
Лео
В обеих ситуациях вам придется использовать псевдоним (или 'table_name.column_name') в одной или нескольких очередях, потому что вы в обоих случаях повторяете имена столбцов.
Please_Dont_Bully_Me_SO_Lords

Ответы:

52

Это не имеет значения. Я никогда не сталкивался с системой, в которой существует реальная разница между выбором 1 и вариантом 2.

Некоторое время назад у Джеффа Этвуда была отличная статья на эту тему. В основном люди яростно спорят и спорят по тем вопросам, в отношении которых нельзя доказать, что они не правы. Или, с другой стороны, те темы, которые можно выиграть только с помощью выносливости в стиле флибустьера, основанной на аргументах последнего человека.

Выберите одно и попросите их сосредоточиться на проблемах, которые действительно влияют на ваш код.

EDIT: если вы хотите повеселиться, попросите их подробно указать, почему их метод лучше для рекурсивных ссылок на таблицы.

Рассел Стин
источник
28
+1, для здравого смысла ... Есть более важные вещи, о которых можно спорить .. Итак, делайте это по-своему (вариант 2)
Чарльз Бретана 02
5
И для саморегулирующегося DRI, когда существует более одного FK, которые ссылаются на один и тот же PK, вы ДОЛЖНЫ нарушить оба «стандарта», поскольку два столбца FK не могут быть названы одинаково ... например, EmployeeTable с EmployeeId PK, SupervisorId FK, MentorId Fk, PartnerId FK и т. д. и т. д. и т. д.
Чарльз Бретана,
76

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

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

Еще один аргумент в пользу соглашения №2 заключается в том, что так была разработана реляционная модель .

Значимость каждого столбца частично передается путем пометки его именем соответствующего домена.

Стивен Хьювиг
источник
4
Синтаксис и семантика SQL на самом деле дают довольно хорошее представление о том, как его следует использовать. например, синтаксис USING означает, что столбцы с одним и тем же доменом должны иметь одинаковое имя, NULL = NULL -> NULL означает, что NULL является «неизвестным», а не «неприменимым», а ON UPDATE CASCADE означает, что ключи должны быть только уникальными, а не неизменяемыми.
Стивен Хьювиг
6
Еще лучше, если она позволяет это: SELECT name, address, amount FROM employees NATURAL JOIN payroll.
однажды,
5
Я бы не стал использовать естественное объединение в развернутом коде, потому что в случае добавления схемы это будет хуже. Но для интерактивных запросов это здорово.
Стивен Хьювиг
3
+1 но всегда есть исключения. Например, если у вас есть два столбца в платежной ведомости, которые являются внешними ключами для сотрудника (например, одна ссылка на человека, которому платят, а вторая - на менеджера с бюджетными полномочиями). Но мы не можем назвать оба внешних ключа employee_id.
Билл Карвин
1
Ключевое слово using специфично для MySql. К сожалению, не работает в T-SQL.
birdus 08
12

Я думаю, это зависит от того, как составлено ваше приложение. Если вы используете ORM или разрабатываете свои таблицы для представления объектов, то вариант 1 может быть для вас.

Мне нравится кодировать базу данных как отдельный слой. Я все контролирую, а приложение просто вызывает хранимые процедуры. Приятно иметь наборы результатов с полными именами столбцов, особенно когда много таблиц соединено и возвращается много столбцов. С таким типом приложения мне нравится вариант 2. Мне очень нравится, чтобы имена столбцов совпадали при объединениях. Я работал со старыми системами, где они не совпадали, и это был кошмар,

КМ.
источник
4
+1 за определение объединений с несовпадающими именами столбцов
Радж Мор
4
в «старых системах» недостаток 8-значных имен вредит намного больше, чем это. Я готов рискнуть и предположить, что наличие PK с именем ID не было основной причиной кошмара в старых системах, с которыми вы имели дело. Кроме того, «это засасывает старые системы» слишком часто используется в разработке программного обеспечения, особенно баз данных. Я регулярно вижу людей, оправдывающих любую данную практику А, основываясь на том, как она работала, исходя из их опыта работы с системой БД, выпущенной более 10 лет назад.
Рассел Стин,
2
сегодняшние современные приложения через несколько лет станут старым дерьмом . вы даже можете переписать интерфейс или использовать данные на другой платформе, но ваши данные (включая имена столбцов) должны выдержать испытание временем.
КМ.
2
Значит, 20 лет назад люди должны были каким-то образом использовать имена столбцов, которые имеют смысл сегодня, даже если в них было всего 8 символов? Форматы хранения данных сильно изменились за последние 20 лет и снова изменятся в следующие 20. Невозможно продемонстрировать, что ваши предпочтения выдержат испытание временем лучше, чем другие перечисленные методы. «имена столбцов» могут сами по себе оказаться «старой чушью» к тому времени, когда люди начнут обсуждать это через 20 лет, поскольку наша способность хранить и управлять данными улучшается. Таблицы - это человеческая конструкция, которая несовершенно представляет отношения данных ...
Рассел Стин,
1
Спасибо за аргументированный интеллектуальный ответ.
Рассел Стин,
3

Ни одно из соглашений не работает во всех случаях, так зачем вообще использовать его? Используй здравый смысл...

например, для таблицы со ссылками на себя, когда существует более одного столбца FK, который ссылается на PK одной и той же таблицы, вы ДОЛЖНЫ нарушить оба «стандарта», поскольку два столбца FK не могут быть названы одинаково ... например , EmployeeTable с EmployeeId PK, SupervisorId FK, MentorId Fk, PartnerId FK, ...

Чарльз Бретана
источник
1
+1 за актуальный ответ технической задачи
DVK
Хороший, применимый ответ, но аргументы в пользу ответа Демса упускают из виду.
JYelton
3

Согласен, что выбирать между ними особо нечего. Для меня гораздо более важным аспектом любого стандарта является «стандартная» часть.

Если люди начинают «заниматься своим делом», они должны быть привязаны к своим нижним силам. ПО МОЕМУ МНЕНИЮ :)

MatBailie
источник
3
+1 за признание того, что последовательность важнее, чем быть «правым» (в данном случае)
Рассел Стин
-1 за попытку применить «глупую последовательность». Старая китайская пословица гласит: «Глупая последовательность - хобгоблин для простых умов».
Чарльз Бретана
@charles: в мире, где разные люди поддерживают код друг друга, часто когда автор ушел, а документация устарела или не существует, это не глупая последовательность. Я так рад, что не работаю с Вами ...
MatBailie
@Dems, без обид, но это глупо по двум причинам. 1) Существуют общие, четко понятые сценарии, когда ЛЮБОЙ стандарт ДОЛЖЕН быть нарушен. (см мой ответ на примеры и 2) , так как по этому вопросу, по крайней мере, стандартный бы добавить очень мало значения, за исключением того, чтобы сделать людей , которые , как стандарты чувствуют себя более комфортно ...
Чарльз Bretana
1
Вы могли бы утверждать, что «ID» более согласован - потому что, как только вы введете «carID» на английском языке в таблицу «cars» или «car»? «Овечий ID» в таблице «овец» или «овцы» - вещи начинают противоречить. Если вы придерживаетесь «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

Соглашение, которое мы используем там, где я работаю, довольно близко к A, за исключением того, что мы называем таблицы во множественном числе (т. Е. «Сотрудники») и используем подчеркивания между именем таблицы и столбцом. Преимущество этого метода в том, что для ссылки на столбец это либо «employee _ id», либо «employee.id», в зависимости от того, как вы хотите получить к нему доступ. Если вам нужно указать, из какой таблицы берется столбец, "employee.employees _ id" определенно избыточен.

Джаретт Миллард
источник
Я не решил, нравятся ли мне имена таблиц во множественном числе. При использовании единственного числа запросы кажутся лучше читаемыми («employee.name» в отличие от «employee.name»). Кажется, что даже в соединениях он читается лучше, когда вы объединяете отдельные записи в другую таблицу. Но имена таблиц во множественном числе кажутся более точными, если думать о таблице, а не о запросе. Я буду придерживаться единственного числа, поскольку это то, что мы используем, но я думаю, что это также правильный путь (хотя опять же, многие не согласны)
MatBailie
Да уж. Думаю, это больше зависит от личных предпочтений и / или того, что вы привыкли видеть.
Джаретт Миллард,
2

Если вы смотрите на код приложения, а не только на запросы к базе данных, некоторые вещи мне кажутся ясными:

  1. Определения таблиц обычно напрямую сопоставляются с классом, который описывает один объект, поэтому они должны быть единичными. Чтобы описать коллекцию объекта, я обычно добавляю «Массив» или «Список» или «Коллекция» к имени в единственном числе, поскольку это более четко, чем использование множественного числа, указывает не только на то, что это коллекция, но и на то, что это за коллекция. это. В этом представлении я вижу имя таблицы не как имя коллекции, а как имя типа объекта, коллекцией которого она является. Администратор баз данных, который не пишет код приложения, может упустить этот момент.

  2. Данные, с которыми я работаю, часто используют «ID» для неключевых целей идентификации. Чтобы избежать путаницы между ключевыми «ID» и неключевыми «ID», в качестве имени первичного ключа мы используем «Ключ» (что это такое, не так ли?) С префиксом имени таблицы или аббревиатурой имя таблицы. Этот префикс (и я оставляю его только для первичного ключа) делает имя ключа уникальным, что особенно важно, потому что мы используем имена переменных, которые совпадают с именами столбцов базы данных, и у большинства классов есть родительский элемент, идентифицируемый по имени родительский ключ. Это также необходимо, чтобы убедиться, что это не зарезервированное ключевое слово, которым является только «Ключ». Чтобы упростить согласованность имен ключевых переменных и обеспечить программы, которые выполняют естественные соединения, внешние ключи имеют то же имя, которое используется в таблице, в которой они являются первичным ключом. Мне не раз приходилось сталкиваться с программами, которые работают намного лучше, используя естественные объединения. По этому последнему пункту я признаю проблему с таблицами, ссылающимися на себя, которые я использовал. В этом случае я бы сделал исключение из правила именования внешнего ключа. Например, я бы использовал ManagerKey в качестве внешнего ключа в таблице Employee, чтобы указать на другую запись в этой таблице.

Брюс Патин
источник
Многие объектно-реляционные сопоставители (ORM), такие как Entity Framework, позволяют сопоставить таблицу с классом с другим именем. Это позволяет вам иметь класс с именем «Пользователь» и таблицу с именем «Пользователи».
Fred
2

Мне нравится соглашение №2 - исследуя эту тему и находя этот вопрос перед тем, как опубликовать свой, я столкнулся с проблемой, когда:

Я выбираю * из таблицы с большим количеством столбцов и присоединяю ее ко второй таблице, которая также имеет большое количество столбцов. Обе таблицы имеют столбец «id» в качестве первичного ключа, а это означает, что я должен специально выбрать каждый столбец (насколько я знаю), чтобы сделать эти два значения уникальными в результате, то есть:

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

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

JYelton
источник
2
SELECT *в любом случае является запретом для (большинства) производственных запросов, так что это не большая причина выбирать стандарт именования.
P Daddy
1
Не возражаю: не могли бы вы дать ссылку на причину, по которой это так? Мне не нравится идея поддерживать имена 80 столбцов в моем запросе.
JYelton
На данный момент не могу найти ссылку (сложно найти "*" в Google), но я обрисую основные моменты: (1) изменения в таблице (таблицах) могут негативно повлиять на ваше приложение, (2) это может быть плохо сказывается на производительности, и (3) явное указание того, какие данные вам действительно нужны, может упростить понимание вашего кода. Эти точки могут расширяться, и есть исключения (как я уже упоминал), но здесь это неуместно. Если вы опубликуете это как новый вопрос, я (и другие) буду рад уточнить детали.
P Daddy
2
Я могу это сделать. Я понимаю выигрыш в производительности, но при редактировании кода должен учитывать затраты времени. Я всегда ищу способы улучшить взаимодействие между приложением и базой данных. Спасибо.
JYelton
1
Я не уверен, что SELECT *это запрещено для большинства производственных запросов. Если это значительно увеличивает скорость разработки и делает ваш код более лаконичным и читаемым, что позволяет вам сосредоточиться на более важных вопросах, почему бы и нет SELECT *? Это очень сильно зависит от обстоятельств каждой ситуации и является компромиссом между многими факторами. Одно правило редко подходит ко всему.
niico
2

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

Росс
источник
1

Я использую соглашение №2. Сейчас я работаю с устаревшей моделью данных, где я не знаю, что стоит в данной таблице. Где вред в многословности?

OMG Пони
источник
1

Как насчет наименования внешнего ключа

role_id

где роль - это роль, которую имеет объект, на который указывает ссылка, по отношению к текущей таблице. Это решает проблему рекурсивной ссылки и нескольких fks на одну и ту же таблицу.

Во многих случаях будет идентично названию таблицы, на которую указывает ссылка. В этом случае он становится идентичным одному из ваших предложений.

В любом случае долго спорить - плохая идея

Йенс Шаудер
источник
0

"Где в" порядке ВНУТРЕННЕГО СОЕДИНЕНИЯ сотрудника НА order.employee_id = employee.id "есть ли необходимость в дополнительной квалификации?".

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

«причина, по которой бизнес-пользователь обращается к идентификатору заказа или идентификатору сотрудника, заключается в предоставлении контекста, но на уровне базы данных у вас уже есть контекст, потому что вы ссылаетесь на таблицу».

Молитесь, скажите мне, если столбец назван «ID», то как это «ссылка [sic] на таблицу» выполняется точно, если только не уточняется эта ссылка на столбец ID точно так, как я говорил?


источник