Могу ли я иметь несколько первичных ключей в одной таблице?

Могу ли я иметь несколько первичных ключей в одной таблице?

Таблица может иметь составной первичный ключ, который является первичным ключом из двух или более столбцов. Например:

CREATE TABLE userdata ( userid INT, userdataid INT, info char(200), primary key (userid, userdataid) ); 

Обновление: вот ссылка с более подробным описанием составных первичных ключей.

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

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

Таблица может иметь несколько ключей-кандидатов. Каждый ключ-кандидат представляет собой столбец или набор столбцов, которые являются UNIQUE, взятые вместе, а также NOT NULL. Таким образом, указать значения для всех столбцов любого ключа-кандидата достаточно, чтобы определить, что существует одна строка, которая соответствует критериям, или вообще не содержит строк.

Ключи-кандидаты являются фундаментальной концепцией в реляционной модели данных.

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

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

Это ответ как на главный вопрос, так и на вопрос Калми о

Какой смысл иметь несколько автогенерирующих столбцов?

Этот код ниже содержит составной первичный ключ. Один из его столбцов автоматически увеличивается. Это будет работать только в MyISAM. InnoDB генерирует ошибку « ERROR 1075 (42000): неверное определение таблицы, может быть только один автоматический столбец, и он должен быть определен как ключ ».

 DROP TABLE IF EXISTS `test`.`animals`; CREATE TABLE `test`.`animals` ( `grp` char(30) NOT NULL, `id` mediumint(9) NOT NULL AUTO_INCREMENT, `name` char(30) NOT NULL, PRIMARY KEY (`grp`,`id`) ) ENGINE=MyISAM; INSERT INTO animals (grp,name) VALUES ('mammal','dog'),('mammal','cat'), ('bird','penguin'),('fish','lax'),('mammal','whale'), ('bird','ostrich'); SELECT * FROM animals ORDER BY grp,id; Which returns: +--------+----+---------+ | grp | id | name | +--------+----+---------+ | fish | 1 | lax | | mammal | 1 | dog | | mammal | 2 | cat | | mammal | 3 | whale | | bird | 1 | penguin | | bird | 2 | ostrich | +--------+----+---------+ 

Первичный ключ – очень неудачная запись из-за коннотации «Первичного» и подсознательной ассоциации, как следствие, с логической моделью. Поэтому я не использую его. Вместо этого я имею в виду суррогатный ключ физической модели и естественный ключ (ы) логической модели.

Важно, чтобы логическая модель для каждой сущности имела по крайней мере один набор «бизнес-атрибутов», которые содержат ключ для объекта. Boyce, Codd, Date et al. Относятся к ним в реляционной модели как к ключам кандидата. Когда мы создаем таблицы для этих объектов, их Ключи-кандидаты становятся естественными ключами в этих таблицах. Только через эти естественные ключи пользователи могут однозначно идентифицировать строки в таблицах; поскольку суррогатные ключи всегда должны быть скрыты от пользователей. Это связано с тем, что суррогатные ключи не имеют никакого коммерческого значения.

Однако физическая модель для наших таблиц во многих случаях будет неэффективной без Суррогатного ключа. Напомним, что незакрытые столбцы для некластеризованного индекса могут быть найдены (в общем) только путем поиска ключа в кластерный индекс (игнорируйте таблицы, выполняемые как кучи на мгновение). Когда наш ansible Natural Key (s) является широким, это (1) расширяет ширину наших некластеризованных листовых узлов, увеличивая требования к хранению и доступ к чтению для поиска и сканирования этого некластеризованного индекса; и (2) уменьшает разветвление от нашего кластерного индекса, увеличивая высоту индекса и размер индекса, снова увеличивая требования к чтению и хранению для наших кластеризованных индексов; и (3) увеличивает требования к кешу для наших кластерных индексов. преследуя другие индексы и данные из кеша.

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

Обратите внимание, что эти преимущества возникают только тогда, когда ключ суррогата как маленький, так и ключ кластеризации. Если в качестве ключа кластеризации используется GUID, ситуация часто будет хуже, чем если бы использовался самый маленький ansible Natural Key. Если таблица организована как куча, тогда 8-байтовый (куча) RowID будет использоваться для ключевых поисков, что лучше, чем 16-байтовый GUID, но менее эффективный, чем 4-байтовое целое.

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

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

Рассмотрим этот пример ::

 ALTER TABLE Persons ADD CONSTRAINT pk_PersonID PRIMARY KEY (P_Id,LastName) 

где кортеж ” (P_Id, LastName) ” требует ограничения уникальности и может быть длинным Unicode LastName плюс 4-байтовое целое число, было бы желательно, чтобы (1) декларативно применяло это ограничение как ” ADD CONSTRAINT pk_PersonID UNIQUE NONCLUSTERED (P_Id , LastName) “и (2) отдельно объявлять небольшой ключ суррогатного ключа как« первичный ключ »кластерного индекса. Стоит отметить, что Анита, возможно, хочет только добавить LastName к этому ограничению, чтобы сделать это закрытым полем, что необязательно в кластерном индексе, потому что все поля покрываются им.

Возможность в SQL Server назначать первичный ключ как некластеризованный является неудачным историческим обстоятельством из-за сочетания значения «предпочтительный естественный или ключ-кандидат» (из Логической модели) со значением «ключ поиска в хранилище» из Физического Модель. Я понимаю, что первоначально SYBASE SQL Server всегда использовал 4-байтовый RowID, будь то в кучу или кластерный индекс, как «ключ поиска в хранилище» из физической модели.

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

Пример:

 Person(id, name, email, street, zip_code, area) 

Между id -> name,email, street, zip_code and area может существовать функциональная зависимость. Но часто zip_code ассоциируется с area и, следовательно, существует внутренняя функциональная зависимость между zip_code -> area .

Таким образом, можно рассматривать его разделение на другую таблицу:

 Person(id, name, email, street, zip_code) Area(zip_code, name) 

Так что это соответствует третьей нормальной форме .

Некоторые люди используют термин «первичный ключ» для обозначения точно целочисленного столбца, который получает свои значения, генерируемые каким-то автоматическим механизмом. Например, AUTO_INCREMENT в MySQL или IDENTITY в Microsoft SQL Server. Вы используете первичный ключ в этом смысле?

Если это так, ответ зависит от марки используемой вами базы данных. В MySQL вы не можете этого сделать, вы получите сообщение об ошибке:

 mysql> create table foo ( id int primary key auto_increment, id2 int auto_increment ); ERROR 1075 (42000): Incorrect table definition; there can be only one auto column and it must be defined as a key 

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

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

Однако вы можете поместить несколько полей в один первичный ключ (составной PK). Это сделает ваши соединения медленнее (особенно, если они больше полей типа строки), а ваши индексы больше, но это может устранить необходимость делать объединения в некоторых дочерних таблицах, так что, насколько производительность и дизайн, возьмите его по делу случай основы. Когда вы это делаете, каждое само поле не уникально, но их комбинация. Если одно или несколько полей в составном ключе также должны быть уникальными, вам нужен уникальный индекс. Скорее всего, если одно поле уникально, это лучший кандидат для ПК.

Теперь время от времени у вас более одного кандидата на ПК. В этом случае вы выбираете один из них как ПК или используете суррогатный ключ (я лично предпочитаю суррогатные ключи для этого экземпляра). И (это важно!) Вы добавляете уникальные индексы к каждому из ключей-кандидатов, которые не были выбраны в качестве ПК. Если данные должны быть уникальными, для этого нужен уникальный индекс, будь то ПК или нет. Это проблема целостности данных. (Обратите внимание, что это также верно в любое время, когда вы используете суррогатный ключ, у людей возникают проблемы с суррогатными ключами, потому что они забывают создавать уникальные индексы на ключах-кандидатах.)

Иногда случаются случаи, когда вам требуется более одного суррогатного ключа (обычно это ПК, если у вас есть). В этом случае вы не больше PK, больше полей с автогенерированными ключами. Большинство БД этого не допускают, но есть способы обойти это. Сначала рассмотрим, может ли второе поле быть рассчитано на основе первого автогенерированного ключа (например, Field1 * -1) или, возможно, необходимость второго автогенерированного ключа на самом деле означает, что вы должны создать связанную таблицу. Связанные таблицы могут быть взаимно однозначными. Вы должны обеспечить это, добавив PK из родительской таблицы в дочернюю таблицу, а затем добавив в таблицу новое автоматически генерируемое поле, а затем все поля, подходящие для этой таблицы. Затем выберите одну из двух клавиш в качестве PK и поместите уникальный индекс на другое (автогенерируемое поле не обязательно должно быть PK). И не забудьте добавить FK в поле, которое находится в родительской таблице. В общем случае, если у вас нет дополнительных полей для дочерней таблицы, вам нужно изучить, почему вы считаете, что вам нужны два автоматически генерируемых поля.

(Изучали их, много)

Может быть только 1 первичный ключ.
Но вы можете иметь несколько альтернативных ключей.

В простом случае это так:

  • В таблице может быть несколько ключей-кандидатов (минимальные столбцы, чтобы однозначно идентифицировать строку).
  • Один из ключей-кандидатов выбирается специально и называется Первичным ключом
  • Все остальные ключи-кандидаты называются альтернативными ключами
  • Клавиши Primary Key и Alternate могут быть составными клавишами s (2 или более столбца)

Источники:
https://en.wikipedia.org/wiki/Superkey
https://en.wikipedia.org/wiki/Candidate_key
https://en.wikipedia.org/wiki/Primary_key
https://en.wikipedia.org/wiki/Compound_key

Хорошие технические ответы были даны лучше, чем я могу. Я могу только добавить к этой теме:

Если вы хотите что-то, что не разрешено / приемлемо, это хороший повод сделать шаг назад.

  1. Понимайте суть причин, почему это неприемлемо.
  2. Подробнее в документах / журнальных статьях / Интернете и т. Д.
  3. Проанализируйте / просмотрите текущий дизайн и укажите основные недостатки.
  4. Рассмотрите и протестируйте каждый шаг во время нового дизайна.
  5. Всегда смотрите вперед и пытайтесь создать адаптивное решение.

Надеюсь, это поможет кому-то.

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

 CREATE t1( c1 int NOT NULL, c2 int NOT NULL UNIQUE, ..., PRIMARY KEY (c1) ); 

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

Да, это возможно в SQL, но мы не можем установить несколько первичных ключей в MsAccess. Тогда я не знаю о других базах данных.

 CREATE TABLE CHAPTER ( BOOK_ISBN VARCHAR(50) NOT NULL, IDX INT NOT NULL, TITLE VARCHAR(100) NOT NULL, NUM_OF_PAGES INT, PRIMARY KEY (BOOK_ISBN, IDX) ); 
  • Используя Rails, как я могу установить свой первичный ключ, чтобы он не был столбцом с целым типом?
  • сделать идентификатор в таблице mysql auto_increment (после факта)
  • Первичный ключ Sqlite для нескольких столбцов
  • Выбор наилучшего первичного ключа + система нумерации
  • Interesting Posts

    Параметрированный запрос в Classic Asp

    Как открыть раздел реестра WOW64 из 64-разрядного приложения .NET

    Как определить, совместим ли SSD в моей Dell?

    Индикатор питания всегда остается включенным после выключения ноутбука

    Установка выбранного значения в формах Django. ChoiceField

    Windows 7 cleartype нечеткость

    Как отключить или изменить горячую клавишу Windows + S в OneNote

    Как исправить / обновить начальное меню в Windows 10? Как добавить / удалить / отредактировать элементы навалом?

    Windows 7 говорит, что 8,6-гигабайтный файл не поместится в 14,7 ГБ пространства?

    Как создается построение Perl’s @INC? (ака Какие способы повлиять на поиск модhive Perl?)

    Загрузка асинхронного файла с помощью панели выполнения

    Можно ли создать загрузочный CD Extra (т. Е. 1 аудиодорожку и 1 загрузочную дорожку данных)?

    У Google Chrome нет автоматической синхронизации закладки, когда пользователь нажимает CTRL-D?

    Как остановить нежелательную анимацию UIButton при изменении названия?

    Конструктор преобразования и оператор преобразования: приоритет

    Давайте будем гением компьютера.