Есть ли веские причины иметь таблицу базы данных без целочисленного первичного ключа? - PullRequest
4 голосов
/ 23 марта 2009

Хотя я и виновен в этом преступлении, мне кажется, что у таблицы не может быть веских причин для того, чтобы у таблицы не было первичного ключа поля идентификации.

Плюсы: - хотите вы этого или нет, теперь вы можете уникально идентифицировать каждую строку в вашей таблице, что раньше вы не могли сделать - Вы не можете выполнить репликацию sql без первичного ключа на вашей таблице

Минусы: - дополнительные 32 бита для каждой строки таблицы

Рассмотрим, например, случай, когда вам нужно сохранить пользовательские настройки в таблице в вашей базе данных. У вас есть столбец для имени параметра и столбец для значения параметра. Первичный ключ не требуется, но наличие целочисленного столбца идентификаторов и использование его в качестве первичного ключа представляется наилучшей практикой для любой таблицы, которую вы когда-либо создавали.

Существуют ли другие причины помимо размера, что каждая таблица не должна просто иметь поле целочисленного идентификатора?

Ответы [ 11 ]

14 голосов
/ 23 марта 2009

Конечно, пример решения с одной базой данных: если у вас есть таблица стран, возможно, имеет смысл использовать код страны ISO 3166-1-alpha-2 в качестве первичного ключа. поскольку это международный стандарт, и делает запросы намного более читабельными (например, CountryCode = 'GB' вместо CountryCode = 28). Аналогичный аргумент может быть применен к кодам валют ISO 4217 .

В решении для базы данных SQL Server, использующем репликацию, ключ UNIQUEIDENTIFIER будет иметь больше смысла, так как GUID требуются для некоторых типов репликации (а также значительно упростит предотвращение конфликтов ключей, если имеется несколько исходных баз данных!).

10 голосов
/ 23 марта 2009

Наиболее наглядным примером таблицы, в которой не не нужен суррогатный ключ, является отношение многие ко многим:

CREATE TABLE Authorship (
  author_id INT NOT NULL,
  book_id   INT NOT NULL,
  PRIMARY KEY (author_id, book_id),
  FOREIGN KEY (author_id) REFERENCES Authors (author_id),
  FOREIGN KEY (book_id) REFERENCES Books (book_id)
);

Я также предпочитаю натуральный ключ при разработке системы маркировки:

CREATE TABLE Tags (
  tag VARCHAR(20) PRIMARY KEY
);

CREATE TABLE ArticlesTagged (
  article_id INT NOT NULL,
  tag        VARCHAR(20) NOT NULL,
  PRIMARY KEY (article_id, tag),
  FOREIGN KEY (article_id) REFERENCES Articles (article_id),
  FOREIGN KEY (tag) REFERENCES Tags (tag)
);

Это имеет некоторые преимущества по сравнению с использованием суррогатного ключа "tag_id":

  • Вы можете обеспечить уникальность тегов, не добавляя лишнее ограничение UNIQUE.
  • Вы запрещаете двум разным тегам иметь одинаковое написание.
  • Зависимые таблицы, которые ссылаются на тег, уже имеют текст тега; им не нужно присоединяться к Tags, чтобы получить текст.
6 голосов
/ 23 марта 2009

Каждая таблица должна иметь первичный ключ. Неважно, если это целое число, GUID или столбец «имя параметра». Тип зависит от требований приложения. В идеале, если вы собираетесь присоединить таблицу к другой, лучше всего использовать GUID или целое число в качестве основного ключа.

3 голосов
/ 23 марта 2009

Каждая таблица должна иметь первичный ключ. Но это не обязательно должен быть идентификатор одного поля. Например, в финансовой системе первичным ключом таблицы журнала может быть идентификатор журнала и номер строки. Это создаст уникальную комбинацию для каждой строки (и идентификатор журнала будет первичным ключом в своей таблице).

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

3 голосов
/ 23 марта 2009

Да, есть веские причины. У вас могут быть семантически значимые истинные ключи, а не искусственные идентификационные ключи. Кроме того, не рекомендуется иметь отдельный первичный ключ с автоинкрементом для таблицы «многие-многие». Есть несколько причин, по которым вы можете выбрать GUID.

При этом я обычно использую автоинкрементные 64-битные целые числа для первичных ключей.

2 голосов
/ 23 марта 2009

Одна из причин, по которой первичный ключ не определен как идентификатор, заключается в том, что первичный ключ определен как GUID или заполнен внешне сгенерированными значениями.

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

2 голосов
/ 23 марта 2009

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

Таким образом, у вас есть таблица типа users и одна таблица типа groups (каждая с первичными ключами), и у вас есть третья таблица с именем users_groups только с двумя столбцами (пользователь и группа), к которым подключены пользователи и группы друг с другом.

Например, строка с user = 3 и group = 6 свяжет пользователя с первичным ключом 3 с группой с первичным ключом 6.

1 голос
/ 11 декабря 2009

Разница в ключе (извините) между естественным первичным ключом и суррогатным первичным ключом заключается в том, что значение естественного ключа содержит информацию, а значение суррогатного ключа - нет.

Почему это важно? Что ж, естественный первичный ключ по определению гарантированно уникален, но его значение равно , а не , как правило, гарантируется, что он останется прежним. Когда он меняется, вы должны обновить его в нескольких местах.

Значение суррогатного ключа не имеет реального значения и просто служит для идентификации этой строки, поэтому его не нужно менять. Это особенность модели, а не самого домена.

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

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

1 голос
/ 23 марта 2009

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

Другая область, где я лично не использую этот подход, если для справочных данных, где обычно у нас есть Описание и Значение

Code, Description
'L', 'Live'
'O', 'Old'
'P', 'Pending'

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

0 голосов
/ 11 октября 2015

Я точно знаю, что некоторые очень умные люди, работающие на веб-гигантов, делают это. Хотя я не знаю, почему их собственные причины, я знаю 2 случая, когда таблицы без PK имеют смысл:

  • Импорт данных. Стол временный. Вставки и сканирование всей таблицы должны быть максимально быстрыми. Также нам нужно принять дубликаты записей. Позже мы очистим данные, но процесс импорта должен работать.
  • Аналитика в СУБД. Идентификация строки бесполезна - если нам нужно это сделать, это не аналитика. Нам просто нужен нереляционный, избыточный, ужасный шарик, который выглядит как таблица. Мы создадим сводные таблицы или материализованные представления, написав соответствующие SQL-запросы.

Обратите внимание, что эти случаи имеют веские причины быть нереляционными. Но обычно ваши таблицы должны быть реляционными, поэтому ... да, им нужен первичный ключ.

...