Почему единственный первичный ключ лучше составных?
Почему отказ от составных ключей в пользу всех таблиц с использованием одного первичного ключа с именем id? Потому что обычно все ORM следуют этому.
ИЗМЕНИТЬ
Я только начал изучать рубин на рельсах, а в книге гибкого развития прагматичным была линия: ---
Рельсы действительно не работают слишком хорошо, если в каждой таблице нет числового первичного ключа. Менее суетливое название столбца.
Тот же тип строки, который я читал, когда учил Учение.
EDIT2
Также проверьте эту ссылку. Я все больше и больше путаюсь в этом: ---
Составляющие первичные ключи в сравнении с уникальным полем идентификатора объекта
Из приведенной выше ссылки: -
* первичный ключ должен быть постоянным и бессмысленным; не суррогатные ключи обычно терпят одно или оба требования, в конечном итоге
Если ключ не является постоянным, у вас есть проблема с будущим обновлением, которая может стать довольно сложной
если ключ не является бессмысленным, то он, скорее всего, изменится, т.е. не будет постоянным; см. выше
Возьмем простой, общий пример: таблица элементов инвентаря. Может возникнуть соблазн сделать номер элемента (номер SKU, штрих-код, код части или что-то еще) первичный ключ, но через год все номера позиций меняются, и вы остаетесь с очень грязным обновлением, проблема с базой данных...
EDIT: есть дополнительная проблема, более практичная, чем философская. Во многих случаях вы каким-то образом найдете определенную строку, затем позже обновите ее или снова найдете (или и то, и другое). С составными ключами есть больше данных, чтобы отслеживать и больше ограничений в предложении WHERE для повторного поиска или обновления (или удаления). Также возможно, что один из ключевых сегментов может измениться за это время!. С суррогатным ключом всегда сохраняется только одно значение (суррогатный идентификатор) и по определению оно не может меняться, что значительно упрощает ситуацию. *
Ответы
Ответ 1
Я не думаю, что есть заявка на одеяло, что вы должны использовать только один первичный ключ с именем id.
Большинство людей используют суррогатный первичный ключ в качестве автоматического генерации int, поскольку он изолирует первичный ключ от когда-либо нуждающегося в изменении, например, если вы сделаете PK именем пользователя, а позже изменили свое юридическое имя. Вам нужно будет обновить PK и все столбцы FK, чтобы отобразить новое имя. если вы использовали суррогатный первичный ключ, вы просто обновляете имя пользователя в одном месте (потому что таблицы соединяются в int не с именем).
Размер первичного ключа важен, потому что PK дублируется в каждый индекс, который вы строите на таблице. Если PK большой (например, строка), у вас меньше ключей на страницу в индексе, и для индекса потребуется больше кэш-памяти. Интс небольшой.
При наличии автоматического приращения int PK поддается хорошому кластеризованному индексу, так как строки хранятся в этом порядке, и нет необходимости возвращаться назад и удалять строки, чтобы вставить новую строку, вы всегда добавляете конец таблицы.
Ответ 2
Единственное реальное ограничение, с которым я столкнулся с использованием составных ключей, использует выражение IN
с подзапросом. Это проблема, потому что подзапрос в выражении IN должен возвращать один столбец (по крайней мере, в T-SQL).
SELECT
emp.Name,
emp.UserDomain,
emp.UserID
FROM
employee emp
WHERE
???? IN (SELECT e.UserDomain, e.UserID FROM ... /* some complex
non-correlated subquery
or CTE */
)
Конечно, всегда есть проблемы, но иногда это может быть неприятно.
Это вряд ли является основанием для исключения сложного ключа в тех местах, где имеет смысл использовать его.
Ответ 3
Вы можете использовать оба. В некоторых случаях при создании связи между сущностью вы можете использовать обе сущности в качестве составного ключа.
Как правило, я использую созданные идентификаторы для сущностей и составных ключей для отношений.
Ответ 4
Ну, это в основном о том, чтобы держать JOINs просто - что проще понять:
SELECT
p.ID, p.Name, p.City,
c.ID, c.Country, c.ISOCode
FROM
dbo.Parent p
INNER JOIN
dbo.Child c on c.ParentID = p.ID
или
SELECT
p.ID, p.Name, p.City,
c.ID, c.Country, c.ISOCode
FROM
dbo.Parent p
INNER JOIN
dbo.Child c ON c.ParentName = p.Name
AND c.ParentCity = p.City
AND c.ParentCountry = p.Country
Если у вас есть составные первичные ключи, любой, кто присоединяется к вашей таблице из дочерней таблицы, должен "перетащить" все эти столбцы, и все эти столбцы также будут присутствовать в дочерней таблице, а операторы JOIN довольно беспорядочны. Гораздо лучше иметь один (даже суррогатный) ключ для JOIN!
Ответ 5
Я работал над приложением с первичным ключом из 11 столбцов. Всегда было весело переписывать список много раз, каждый раз, когда я хотел гарантировать, что я обновляю одну строку. Это был драйвер ошибок, MS-Access не смог справиться с более чем 10 столбцами в ПК и т.д.
Большие составные клавиши - это дизайнерские запахи, которые означают, что таблица содержит гетерогенные объекты или дизайнер не был действительно уверен, что это уникально для каждого объекта. (Предположим, что цвет волос, цвет глаз и вес тела должны быть достаточными для уникальной идентификации сотрудника - что не является хорошим ключом, потому что вам понадобится все больше и больше столбцов, чтобы заставить его работать, и в конечном итоге это будет включать поля которые нестабильны и меняются много, например, вес, или для некоторых людей цвет волос или отсутствие там.)
Ответ 6
-
Для ORM единичная идентификация
столбец с постоянным именем
table_id проще, чем составной
ключ. Но каждая хорошая поддержка ORM
составные клавиши.
-
Простой PK может быть легко
"автоинкремент" по базе данных.
Это не выполняется для составного
ключ.
-
Простую PK также проще использовать в
запросы. Когда вам нужно присоединиться, вы
нужно использовать только один столбец
отношения.
Это не означает, что простые PK лучше, чем композитные.
Ответ 7
Объекты программирования OO имеют личность независимо от их содержимого. Строки (кортежи) в реляционных базах данных определяются только их содержимым. Поэтому, когда вы действительно делаете ORM, то есть отображаете объекты с объектно-ориентированного языка программирования в реляционную базу данных, должен быть предоставлен дополнительный идентификатор, отличный от полей и/или свойств, которые объект имеет в программе, - если только один или несколько из них как-то известно, идентифицировать объекты однозначно.
Ответ 8
Ваш вопрос сильно связан с суррогатными (или искусственными) ключами против естественных ключей. Я думаю, что это не так, что составные ключи менее используются, но клавиши Естественные (будь они составные или простые) менее предпочтительны, чем искусственные.
Традиционная теория реляционных баз данных в основном касалась "естественных" ключей (те, которые имеют смысл с точки зрения бизнес-точки), и в этом случае составные ключи часто встречаются... естественно.
Но в последующие годы дизайн базы данных благоприятствовал (хотя и не исключительно) "искусственному" (суррогатному) шаблону ключа, обычно порядковому числу, не имеющему делового значения, только служит для однозначного определения записи в таблице (и возможно, объект в верхнем слое).
Ответ 9
Хотя я согласен с большинством причин, высказанных другими респондентами, моя основная причина предпочитать одноколоночный целочисленный ключ заключается в том, что он значительно упрощает запись пользовательского интерфейса.
Если вы используете какой-то элемент управления списком для представления своих данных (список, список, поле со списком и т.д.), вы можете однозначно связать каждую запись с представлением своей базы данных с помощью целого целочисленного значения, хранящегося в элементе. Большинство предварительно написанных компонентов уже позволяют вам привязывать целое к каждому элементу, а для тех, кто этого не делает, очень просто расширить компонент, чтобы сделать это.
Если вы передаете данные между серверным приложением и веб-страницей, гораздо проще хранить одно идентификационное значение в атрибуте id виджета, который представляет данные, чем для компоновки и анализа многозначных идентификаторов.