Я недавно исследовал концепцию ROWGUID и наткнулся на этот вопрос. Этот ответ дал понимание, но привел меня в другую кроличью нору с упоминанием об изменении значения первичного ключа.
Я всегда понимал, что первичный ключ должен быть неизменным, и мой поиск после прочтения этого ответа дал только ответы, которые отражают то же, что и передовой опыт.
При каких обстоятельствах значение первичного ключа необходимо изменить после создания записи?
database-design
primary-key
5crammed
источник
источник
Ответы:
Если вы использовали имя человека в качестве первичного ключа и его имя изменилось, вам необходимо изменить первичный ключ. Это то, что
ON UPDATE CASCADE
используется, так как по существу каскадные изменения касаются всех связанных таблиц, которые имеют отношение внешнего ключа к первичному ключу.Например:
А
SELECT
против обеих таблиц:Возвращает:
Если мы обновим
PersonKey
столбец и снова запустимSELECT
:мы видим:
Рассматривая план вышеприведенного
UPDATE
оператора, мы ясно видим, что обе таблицы обновляются одним оператором обновления благодаря внешнему ключу, определенному какON UPDATE CASCADE
:нажмите на изображение выше, чтобы увидеть его в большей ясности
Наконец, мы очистим наши временные таблицы:
Удобнее всего 1 способ сделать это с помощью суррогатных ключей будет:
Для полноты, план для оператора update очень прост и показывает одно преимущество для суррогатных ключей, а именно, необходимо обновить только одну строку, в отличие от каждой строки, содержащей ключ в сценарии с естественным ключом:
Вывод из двух
SELECT
утверждений выше:По сути, результат примерно одинаков. Одним из основных отличий является то, что широкий естественный ключ не повторяется в каждой таблице, где встречается внешний ключ. В моем примере я использую
VARCHAR(200)
столбец для хранения имени человека, что требует использованияVARCHAR(200)
везде . Если есть много строк и много таблиц, содержащих внешний ключ, это приведет к большой потере памяти. Заметьте, я не говорю о том, что дисковое пространство теряется, так как большинство людей говорит, что дисковое пространство настолько дешево, что оно по существу свободно. Память, однако, дорогая и заслуживает заботы. Использование 4-байтового целого числа для ключа сэкономит большой объем памяти, если учесть среднюю длину имени около 15 символов.Касательно вопроса о том, как и почему ключи могут изменяться, возникает вопрос о том, почему следует выбирать естественные ключи вместо суррогатных ключей, что является интересным и, возможно, более важным вопросом, особенно в тех случаях, когда производительность является целью проектирования. Смотрите мой вопрос здесь об этом.
1 - http://weblogs.sqlteam.com/mladenp/archive/2009/10/06/Why-I-prefer-surrogate-keys-instead-of-natural-keys-in.aspx
источник
Хотя вы можете использовать ключ, который является естественным и / или изменяемым, в качестве вашего PK, по моему опыту, это приводит к проблемам, которые часто можно предотвратить с помощью PK, который удовлетворяет следующим условиям:
Например, многие компании в США пытаются использовать номера социального страхования в качестве персональных идентификационных номеров (и ПК) в своих системах. Затем они сталкиваются со следующими проблемами: ошибки ввода данных, приводящие к необходимости исправления нескольких записей, люди, у которых нет SSN, люди, чьи SSN изменены правительством, люди с дублирующимися SSN.
Я видел каждый из этих сценариев. Я также видел компании, которые не хотели, чтобы их клиенты были «просто числом», что означало, что их PK в конечном итоге был «первый + средний + последний + DOB + почтовый индекс» или что-то подобное. Несмотря на то, что они добавили достаточно полей, чтобы практически гарантировать уникальность, их запросы были ужасными, и обновление любого из этих полей означало поиск проблем с согласованностью данных.
По моему опыту, PK, созданный самой базой данных, почти всегда является лучшим решением.
Я рекомендую эту статью для дополнительных указателей: http://www.agiledata.org/essays/keys.html
источник
Первичный ключ может быть изменен при синхронизации. Это может быть в том случае, если у вас отключен клиент, и он через определенные промежутки времени синхронизирует данные с сервером.
Несколько лет назад я работал в системе, где все данные о событиях на локальном компьютере имели отрицательные идентификаторы строк, такие как -1, -2 и т. Д. Когда данные были синхронизированы с сервером, идентификатор строки на сервере был применен к клиент. Допустим, следующий идентификатор строки на сервере был 58. Тогда -1 станет 58, -2 59 и так далее. Это изменение идентификатора строки будет каскадно добавлено ко всем дочерним записям FK на локальном компьютере. Этот механизм также использовался для определения того, какие записи были ранее синхронизированы.
Я не говорю, что это был хороший дизайн, но это пример изменения первичного ключа с течением времени.
источник
Любой дизайн, который предполагает изменение
PRIMARY KEY
на регулярной основе, является рецептом для катастрофы. Единственной хорошей причиной для его изменения будет объединение двух ранее отдельных баз данных.Как указывает @MaxVernon, могут происходить случайные изменения - затем использовать
ON UPDATE CASCADE
, хотя в настоящее время большинство систем используют идентификатор в качестве суррогатаPRIMARY KEY
.Такие пуристы, как Джо Селко и Фабиан Паскаль (сайт, которому стоит следовать) не согласны с использованием суррогатных ключей, но я думаю, что они проиграли именно эту битву.
источник
Стабильность является желательным свойством для ключа, но это относительная вещь, а не абсолютное правило. На практике часто бывает полезно изменить значения ключей. В реляционных терминах данные можно идентифицировать только по их (супер) ключам. Отсюда следует, что если в данной таблице имеется только один ключ, то различие между A) изменением значения ключа или B) заменой набора строк в таблице некоторым аналогичным или другим набором строк, содержащих другие значения ключа, по существу проблема семантики, а не логики.
Более интересным примером является случай таблицы с несколькими ключами, где значения одного или нескольких из этих ключей могут измениться относительно других значений ключа. Возьмите пример таблицы Employee с двумя ключами: LoginName и Badge Number. Вот пример строки из этой таблицы:
Если ZoeS потеряет свой значок, то, возможно, ей назначат новый значок и получат новый номер значка:
Позже она может решить изменить свое имя пользователя:
Оба ключевых значения изменены - по отношению друг к другу. Обратите внимание, что не обязательно имеет значение, какой из них считается «основным».
На практике «неизменность», т. Е. Абсолютно никогда не меняющее значение, недостижима или, по крайней мере, невозможна для проверки. В той степени, в которой это изменение имеет значение вообще, самый безопасный курс, вероятно, предполагает, что любой ключ (или любой атрибут) может потребоваться изменить.
источник
Интересно, что связанный вопрос о типе ROWGUID предоставляет свой вариант использования: когда у вас есть конфликтующие первичные ключи в базах данных, которые необходимо синхронизировать. Если у вас есть две базы данных, которые необходимо согласовать, и они используют последовательности для первичных ключей, вам нужно изменить один из ключей, чтобы он мог оставаться уникальным.
В идеальном мире этого никогда бы не случилось. Для начала вы бы использовали GUID для первичных ключей. Реально, однако, у вас может даже не быть распределенной базы данных, когда вы начнете проектировать, и преобразование ее в GUID могло быть попыткой, которая была расставлена по приоритетам ниже, чтобы сделать ее распределенной, потому что это считалось более значительным, чем реализация обновления ключа. Это может произойти, если у вас большая кодовая база, которая зависит от целочисленных ключей и потребует серьезной ревизии для преобразования в GUID. Существует также тот факт, что разреженные идентификаторы GUID (идентификаторы GUID, которые не очень близки друг к другу, что происходит, если вы генерируете их случайным образом, как вы должны), могут также вызывать проблемы для определенных типов индексов, что означает, что вы хотите избежать использования их как первичные ключи (упомянутые Байроном Джонсом ).
источник
Один из возможных сценариев, скажем, у вас есть филиалы с уникальным идентификатором, и вы знаете, что они не будут дублироваться среди филиалов, поскольку у них есть уникальный стартовый персонаж. Филиалы загружают данные в основную таблицу. Там записи обрабатываются, а затем присваивается главный идентификатор. Пользователям необходим доступ к записям, как только они загружены, даже если они еще не обработаны. Вы хотите, чтобы основной идентификатор был основан на обработанном заказе, и вы не всегда будете обрабатывать в том порядке, в котором были загружены записи. Я знаю немного сфабриковано.
источник
Представьте себе ситуацию, когда кто-то выбрал номер социального страхования (NIN) в качестве первичного ключа и оператор каким-то образом вставил строку с неправильным NIN. После вставки значения есть два способа исправить ошибку:
источник