Таким образом, я видел несколько упоминаний о суррогатном ключе в последнее время, и я не действительно уверен, что это и как это отличается от первичного ключа.
Я всегда предполагал, что идентификатор был моим первичным ключом в таблице как это:
Users
ID, Guid
FirstName, Text
LastName, Text
SSN, Int
однако, Википедия определяет суррогатный ключ как "Суррогатный ключ в базе данных, уникальный идентификатор или для объекта в смоделированном мире или для объекта в базе данных. Суррогатный ключ не получен из данных приложения".
Согласно Википедии, похоже, что идентификатор является моим суррогатным ключом, и мой первичный ключ мог бы быть SSN+ID? Действительно ли это правильно? Это - плохой дизайн таблицы?
Предположение, что дизайн таблицы является звуковым, что-то вроде этого было бы плохо, для таблицы, где данные ничего не имели уникальным об этом?
LogEntry
ID, Guid
LogEntryID, Int [sql identity field +1 every time]
LogType, Int
Message, Text
Нет, Ваш ID может быть одновременно и суррогатным ключом (что означает, что он не является "производным от данных приложения", например, искусственным ключом), и он должен быть и Вашим первичным ключом.
Первичный ключ используется для уникальной и безопасной идентификации любой строки в Вашей таблице. Он должен быть стабильным, уникальным, а НЕ NULL - "искусственный" ID обычно обладает этими свойствами.
Обычно я бы не рекомендовал использовать "естественные" или реальные данные для первичных ключей - не уверен ли REALLY 150%, что НИКОГДА не изменится?? Швейцарский эквивалент SSN, например, меняется каждый раз, когда женщина выходит замуж (или разводится) - вряд ли это идеальный кандидат. И он не гарантированно будет уникальным, либо ......
Чтобы избавить себя от всего этого горя, просто используйте суррогатный (искусственный) ID, который определяется системой, уникален, и никогда не меняется и не имеет никакого прикладного значения (кроме того, что является вашим уникальным ID).
У Скотта Амблера есть довольно хорошая статья здесь, в которой есть "глоссарий" всех различных ключей и что они означают - вы найдете натуральный, суррогатный, первичный ключ и еще несколько.
.Причина, по которой пуристы баз данных ввязываются в объятия о суррогатных ключах, заключается в том, что при неправильном использовании они могут допускать дублирование данных, что является одним из зол, которое хороший дизайн баз данных призван изгнать.
Например, предположим, что у меня была таблица адресов электронной почты для списка рассылки. Я бы хотел, чтобы они были уникальными, верно? Нет смысла иметь 2, 3 или n записей одного и того же адреса электронной почты. Если я использую email_address
в качестве основного ключа ( который является естественным ключом -- он существует в виде данных независимо от структуры базы данных, которую вы создали), это гарантирует, что у меня никогда не будет дубликата адреса электронной почты в списке рассылки.
Однако, если в качестве суррогатного ключа у меня есть поле под названием id
, то у меня может быть любое количество дублирующих друг друга адресов электронной почты. Это будет плохо, если в списке будет 10 строк одного и того же адреса электронной почты, и все они будут содержать противоречивую информацию о подписке в других столбцах. Какой из них правильный, если он есть? Невозможно сказать! После этого, ваша целостность данных будет нарушена. Нет другого способа исправить данные, кроме как просматривать записи по одному, спрашивать у людей, какая информация о подписке действительно верна и т.д.
Причина, по которой этого хотят неюристы, в том, что это упрощает использование стандартизированного кода, потому что вы можете положиться на ссылку на единственную строку базы данных с целочисленным значением. Если бы у вас был естественный ключ, скажем, набора ( client_id, email, category_id )
, программист возненавидит кодирование вокруг этого экземпляра! Это как бы нарушает инкапсуляцию классовой кодировки, так как требует от программиста глубокого знания структуры таблицы, а метод delete может иметь разный код для каждой таблицы. Фу!
Так что очевидно, что этот пример слишком упрощен, но он иллюстрирует суть дела.
Во-первых, Суррогатный ключ - это ключ, который искусственно генерируется в БД, как уникальное значение для каждой строки в таблице, и который не имеет никакой зависимости ни от какого другого атрибута в таблице.
Теперь фраза Первичный ключ представляет собой красную селедку. Является ли ключ первичным или альтернативным, ничего не значит. Важно то, для чего используется ключ. Ключи могут служить двум функциям, которые фундаментально несовместимы друг с другом.
Так что ответ прост.... Always (везде, где Вас волнует целостность/согласованность данных) используйте естественный ключ и, при необходимости, оба! Когда естественный ключ является составным, или длинным, или недостаточно стабильным, добавьте альтернативный Суррогатный ключ (например, как автоинкрементирующее целое число) для использования в качестве целей FK в дочерних таблицах. Но рискуя потерять целостность данных в вашей таблице, НЕ удаляйте естественный ключ из основной таблицы.
Чтобы сделать это кристально ясно, давайте приведем пример. Скажем, у вас есть таблица с банковскими счетами в ней... Естественным ключом может быть банковский номер маршрута и номер счета в банке. Чтобы избежать использования этого двойного составного ключа в каждой записи транзакции в таблице транзакций, вы можете решить поместить искусственно сгенерированный суррогатный ключ в таблицу BankAccount, которая является всего лишь целым числом. Но лучше сохранить естественный ключ! Если бы вы этого не сделали, если бы у вас не было и составного естественного ключа, вы вполне могли бы закончить с двумя строками в таблице следующим образом
id BankRoutingNumber BankAccountNumber BankBalance
1 12345678932154 9876543210123 $123.12
2 12345678932154 9876543210123 ($3,291.62)
Теперь, какая из них правильная?
Чтобы выделить из комментариев ниже, Какая польза от того, что вы можете "идентифицировать строку "? Совсем не хорошо, как мне кажется, потому что нам нужно уметь идентифицировать, какой банковский счет строка представляет! Идентификация строки важна только для технических функций внутренней базы данных, таких как объединение в запросах, или для операций ограничения FK, которые, если/когда они необходимы, все равно должны использовать суррогатный ключ, а не естественный ключ.
Вы правы в том, что неправильный выбор естественного ключа, а иногда даже лучший доступный выбор естественного ключа, может не быть по-настоящему уникальным или гарантированно не допускать дубликатов. Но любой выбор лучше, чем отсутствие выбора, так как это, по крайней мере, предотвратит дублирование строк для одинаковых значений в атрибутах, выбранных в качестве естественного ключа. Эти проблемы могут быть сведены к минимуму соответствующим выбором ключевых атрибутов, но в некоторых случаях они неизбежны и должны быть решены. Но все же лучше это сделать, чем допустить попадание в базу данных некорректных неточных или избыточных данных.
Что касается "простоты использования" Если все, для чего вы используете естественный ключ, это ограничение на вставку дубликатов строк, а вы используете другой, суррогатный ключ в качестве мишени для ограничений FK, то я не вижу никаких проблем, связанных с простотой использования.
Идея наличия целочисленного идентификатора в качестве первичного ключа (даже это ничего не значит) предназначена для целей индексирования. Тогда вы, вероятно, определите естественный ключ как уникальное ограничение на вашей таблице. Таким образом, вы получите лучшее из обоих миров. Быстрая индексация с вашим ID полем, и каждая строка сохраняет свою естественную уникальность. Тем не менее, некоторые люди клянутся, просто используя естественный ключ.
Ого, этим вопросом вы открыли банку с червями. Пуристы базы данных скажут вам никогда не использовать суррогатные ключи (как было сказано выше). С другой стороны, суррогатные ключи могут иметь некоторые огромные преимущества. Я использую их постоянно.
В SQL Server, суррогатный ключ обычно является автоматически создаваемым идентификационным значением, которое SQL Server генерирует для вас. Оно не имеет никакого отношения к фактическим данным, хранящимся в таблице. Противоположностью этому является ключ Естественный. Примером может служить номер социального страхования. Он действительно имеет отношение к данным, хранящимся в таблице. Существуют преимущества натуральных ключей, но, IMO, преимущества использования суррогатных ключей перевешивают натуральные ключи.
Я заметил в вашем примере, что у вас есть GUID для первичного ключа. Как правило, Вы не хотите использовать GUID в качестве первичного ключа. Они большие, громоздкие и часто могут быть вставлены в вашу базу данных случайным образом, что приводит к большой фрагментации.
Randy
На самом деле есть три вида ключей, о которых стоит поговорить. Первичный ключ - это то, что используется для уникальной идентификации каждой строки в таблице. Замещающий ключ - это искусственный ключ, который создается с помощью этого свойства. Естественный ключ - это первичный ключ, который получается из фактических данных реальной жизни.
В некоторых случаях естественный ключ может быть громоздким, поэтому может быть создан суррогатный ключ для использования в качестве чужеродного ключа и т.д. Например, в журнале или дневнике PK может быть дата, время и полный текст записи (если возможно добавить две записи одновременно). Очевидно, что было бы плохо использовать все это каждый раз, когда вы хотите идентифицировать строку, так что вы можете сделать "log id". Это может быть последовательный номер (наиболее распространенный), или дата плюс последовательный номер (как 20091222001), или что-то другое. Некоторые натуральные ключи могут работать так же хорошо, как и первичный ключ, например, VIN-номера автомобилей, студенческие ID-номера (если они не используются повторно), или в случае объединения таблиц, PK двух соединяемых таблиц.
Это просто обзор выбора клавиш для таблиц. Здесь есть на что обратить внимание, хотя в большинстве магазинов вы обнаружите, что они идут в комплекте с "добавлением идентификационного столбца в каждую таблицу, и это наш основной ключ". Затем вы получите все проблемы, которые с этим связаны.
В вашем случае я думаю, что LogEntryID для ваших элементов журнала кажется разумным. Является ли идентификатор FK к таблице Пользователей? Если нет, то я могу усомниться в том, что оба ID и LogEntryID находятся в одной таблице, так как они избыточны. Если да, то я бы изменил имя на user_id или что-то подобное.
. Использование Guid
в качестве первичного ключа для вашей таблицы Users
: идеально .
Если вы не планируете предоставлять данные LogEntry
во внешнюю систему или объединять их с другой базой данных, я бы просто использовал увеличивающуюся int
вместо Guid
в качестве первичного ключа. С ним легче работать, и он будет занимать немного меньше места, что может быть значительным для огромного бревна, растянувшегося на несколько лет.