Чи повинна кожна таблиця мати первинний ключ?


340

Я створюю таблицю бази даних, і мені не присвоєний логічний первинний ключ. Отже, я думаю про те, щоб залишити його без первинного ключа, але я відчуваю трохи провини в цьому. Повинен я?

Чи повинна кожна таблиця мати первинний ключ?


5
Чи можете ви детальніше розповісти про таблицю? Хоча відповідь, мабуть, "так".
Райан Бейр

7
Так, кожна таблиця повинна мати первинний ключ.
Syed Tayyab Ali

Відповіді:


313

Коротка відповідь: так .

Довга відповідь:

  • Вам потрібно, щоб ваш стіл був приєднаний до чогось
  • Якщо ви хочете, щоб ваша таблиця була згрупована, вам потрібен якийсь первинний ключ.
  • Якщо для оформлення столу не потрібен первинний ключ, переосмисліть дизайн: швидше за все, вам щось не вистачає. Навіщо вести однакові записи?

У MySQL механізм зберігання InnoDB завжди створює первинний ключ, якщо ви не вказали його чітко, таким чином, роблячи додатковий стовпець, до якого ви не маєте доступу.

Зауважте, що первинний ключ може бути складеним.

Якщо у вас є таблиця посилань з багатьма на багато, ви створюєте первинний ключ для всіх полів, задіяних у посиланні. Таким чином, ви гарантуєте, що у вас немає двох або більше записів, що описують одне посилання.

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

А оскільки будь-який первинний ключ включає створення унікального індексу, вам слід оголосити його і отримати як логічну послідовність, так і продуктивність.

Дивіться цю статтю в моєму блозі, чому завжди слід створювати унікальний індекс унікальних даних:

PS Є кілька дуже-дуже особливих випадків, коли вам не потрібен первинний ключ.

В основному вони включають в себе таблицю журналів , які не мають будь - яких індексів для підвищення продуктивності.


у них все ще є первинний ключ, складний
Крістоф

2
@annakata: у них повинен бути складений первинний ключ
Quassnoi

1
"І оскільки будь-який ПЕРШИЙ КЛЮЧ передбачає створення УНІКАЛЬНОГО індексу", це не відповідає дійсності для Oracle. Можна використовувати не унікальний індекс для примусового використання первинного ключа. Насправді іноді ПОТРІБНО, щоб унікальні та ПК обмеження використовували не унікальні індекси.
Стефанія Сторінка

3
Просто коментар до риторичного запитання «Навіщо вести однакові записи?». Зауважте, що просто додавання ПК не забезпечить дублювання. Часто ПК не видно користувачеві, отже, що важливо - у видимих ​​полях, які можуть містити повторювані дані. Залежно від вашого дизайну це може бути бажаним чи ні.
Роско

1
Ключі не мають нічого спільного з приєднанням. І аргумент кластеризації залежить від того, яку СУБД ви використовуєте, і змішує логічні та фізичні міркування.
Джон Хегленд

36

Завжди найкраще мати первинний ключ. Таким чином він відповідає першій нормальній формі і дозволяє продовжувати шлях нормалізації бази даних .

Як заявили інші, є деякі причини, щоб не було первинного ключа, але більшість не буде завдано шкоди, якщо є первинний ключ


5
@PaulSuart Дані не завжди повинні бути у їх звичайних формах. Насправді, коли дані стають величезними, вони не повинні зберігатись у нормальній формі, інакше доступ до даних буде жахливо повільним для запитів, пов’язаних з приєднанням таблиці тощо. Нормальні форми - це "ідеалізація" і практично можлива лише тоді, коли не очікується зростання даних. величезний.
Pacerier

13

Практично в будь-який час я створював таблицю без первинного ключа, думаючи, що мені це не знадобиться, я закінчився поверненням і додав його. Тепер я створюю навіть свої таблиці приєднання з автоматично сформованим полем ідентичності, яке я використовую як основний ключ.


13
Таблиця приєднання - це первинний ключ - складений, який складається з ПК обох записів, що з'єднуються. Наприклад, СТВОРИТИ ТАБЛИЦЮ PersonOrder (PersonId int, OrderId int, PRIMARY KEY (PersonId, OrderId)).
Кіт Вільямс

3
Так, але що робити, якщо таблиця посилань має також третій атрибут, давайте скажемо "OrderDate". Чи додали б ви це до складеного ключа? ІМХО ні - тому що це ще більше скорочується і не обслуговує символів, що не зводяться до первинного ключа.
stevek

13

За винятком кількох дуже рідкісних випадків (можливо, таблиця відносин «багато-багато» або таблиця, яку ви тимчасово використовуєте для масового завантаження величезних обсягів даних), я б сказав:

Якщо він не має первинного ключа, це не таблиця!

Марк


10
Строго кажучи, що речення неправильне. Таблиці можуть бути "Переглянути таблиці", створені вашою мовою запитів. RDBMS складається з відносин, а не таблиць. У цьому реченні повинно бути сказано: "Якщо він не має первинного ключа, це не відношення!".
stevek

Або, можливо, "якщо немає кандидатських ключів, то це не реляційна таблиця". Але подивіться дуже рідкісні випадки, коли нормально мати таблицю, яка не представляє відношення.
Уолтер Мітті

Чому б таблиця "багато на багато" не мала первинний ключ? Ви можете створити окремий первинний ключ, а потім створити унікальний індекс для сурогату іноземних ключів. Я думаю, що краще мати первинний ключ на кожному столі. Навіть у таблиці масового завантаження ви можете окремо визначити первинний ключ, не включений до імпортованих даних, оскільки це може допомогти вам ідентифікувати повторювані записи в процесі ETL. Мені здається, що кожна таблиця все-таки повинна мати первинний ключ, навіть якщо це трохи більше місця для зберігання. Таблиця, створена представленням, - це підмножина таблиці, а не сама таблиця.
Джон Ернест

1
У таблиці відносин багато-багато можна створити складений первинний ключ, що складається з обох ідентифікаторів відносин.
Яап

8

Просто додайте його, ви будете шкодувати пізніше, коли цього не зробили (вибір, видалення. Посилання тощо)


8

Чи вам коли-небудь потрібно буде приєднати цю таблицю до інших таблиць? Чи потрібен спосіб однозначної ідентифікації запису? Якщо відповідь "так", вам потрібен первинний ключ. Припустимо, ваші дані - це щось на зразок таблиці клієнтів, яка містить імена людей, які є клієнтами. Можливо, немає природного ключа, оскільки вам потрібні адреси, електронні листи, номери телефонів тощо, щоб визначити, чи відрізняється ця Саллі Сміт від тієї Саллі Сміт, і ви будете зберігати цю інформацію у відповідних таблицях, оскільки людина може мати кілька телефонів, доповнень , електронні листи та ін. Припустимо, Салі Сміт виходить заміж за Джона Джонса та стає Саллі Джонсом. Якщо у вас немає штучного ключа на столі, під час оновлення імені ви просто змінили 7 Sally Smiths на Sally Jones, хоча лише одна з них вийшла заміж і змінила її ім'я.

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

Я виявив, що в будь-який час у мене немає природного ключа, штучний ключ - це абсолютна необхідність для підтримки цілісності даних. Якщо у вас є природний ключ, ви можете використовувати його як ключове поле. Але особисто, якщо природний ключ - це одне поле, я все-таки віддаю перевагу штучному ключу та унікальному індексу природного ключа. Ви пошкодуєте пізніше, якщо не покладете його.


6

Це хороша практика мати ПК на кожному столі, але це НЕ ОБОВ'ЯЗКОВО. Швидше за все, вам знадобиться унікальний індекс та / або кластерний індекс (який є ПК або ні) залежно від ваших потреб.

Перегляньте розділи Основні ключі та кластеризовані індекси в Книгах онлайн (для SQL Server)

" ПЕРШИЧНІ КЛЮЧОВІ обмеження ідентифікують стовпчик або набір стовпців, які мають значення, що однозначно ідентифікують рядок у таблиці. Жоден два рядки таблиці не можуть мати однакове значення первинного ключа. Ви не можете ввести NULL для будь-якого стовпця в первинному ключі. Ми рекомендуємо використовувати невеликий цілий стовпець у якості основного ключа. Кожна таблиця повинна мати первинний ключ. Стовпець або комбінація стовпців, які кваліфікуються як значення первинного ключа, згадуються як кандидатський ключ. "

Але перевірте це також: http://www.aisintl.com/case/primary_and_foreign_key.html



4
ця сторінка досить дурна. По-перше, первинний ключ необхідний з міркувань продуктивності. Читаючи його сторінку, я дізнаюся, що додавати ідентифікатор до книжкової таблиці марно, оскільки текст книги унікальний; Очевидно, хлопець ніколи не працював з базами даних. Але у нього також є проблеми в розумінні того, що він критикує. Сторінка написала, що 1) значення ПК посилається на рядок 2) ви можете приєднати 2 таблиці до будь-якого набору стовпців. Протиріччя немає. Дивовижно, що автор академічної статті не розуміє самих основ теорії реляції.
Федеріко Різолі

1
"По-перше, первинний ключ потрібен з міркувань продуктивності". Це неправильно, ПК не впливає на продуктивність. Відсутність ПК може спричинити багато проблем (визначення рядка, приєднання тощо), але продуктивність не одна з них. Коли ви створюєте ПК на столі, SQL-сервер створює унікальний кластерний індекс, що індекс впливає на продуктивність, а не на саму ПК. Як справжній приклад, у моїй таблиці є кластерний індекс стовпця дати та ПК у полі GUID, оскільки мої рядки мають бути фізично упорядковані над стовпцем дати в таблиці, оскільки всі запити мають діапазон дат (у моєму випадку).
endo64

Цей кластерний індекс - це смак первинного ключа, створеного SQL Server та кількома іншими СУБД. Ви впевнені, що корисно це використовувати? Наприклад, у MySQL це не з кількох незадокументованих причин.
Федеріко Розцолі

1
Майте на увазі, що GUID не є оптимальним типом ПК, в InnoDB. Усі індекси містять посилання на ПК, тому, чим більший PK, тим більшими будуть усі інші індекси.
Федеріко Різолі

6

Не погоджуйтесь із запропонованою відповіддю. Коротка відповідь: НІ .

Мета первинного ключа - однозначно визначити рядок на столі, щоб сформувати зв’язок з іншою таблицею. Традиційно для цього використовується цілочисельне значення з автоматичним збільшенням, але для цього є варіанти.

Хоча є випадки, наприклад, реєстрація даних часових рядів, коли існування такого ключа просто не потрібно і просто займає пам'ять. Зробити рядок унікальним просто ... не потрібно!

Невеликий приклад: Таблиця A: LogData

Columns:  DateAndTime, UserId, AttribA, AttribB, AttribC etc...

Первинний ключ не потрібен.

Таблиця B: Користувач

Columns: Id, FirstName, LastName etc. 

Первинний ключ (Id), необхідний для використання в якості "зовнішнього ключа" для таблиці LogData.


3

Я знаю, що для того, щоб використовувати певні функції gridview в .NET, вам потрібен первинний ключ, щоб gridview знав, який рядок потребує оновлення / видалення. Загальна практика повинна мати первинний ключ або кластер первинного ключа. Я особисто віддаю перевагу колишньому.


3

Щоб зробити це майбутнім доказом, ви дійсно повинні. Якщо ви хочете його повторити, вам знадобиться такий. Якщо ви хочете приєднати його до іншого столу, то ваше життя (і життя бідних дурнів, яким доведеться підтримувати його в наступному році) буде набагато простіше.


Я не впевнений, що це ще потрібно, але "зробити це тому, що в іншому випадку комусь доведеться боротися з наслідками пізніше", достатньо, щоб змусити мене помилитися на стороні цього. Я завжди можу просто скинути стовпчик пізніше, якщо здається, що варто спробувати зменшити його…
ArtOfWarfare

3

Я в ролі підтримки додатків, створених командою з офшорних розробників. Тепер у мене виникають всілякі проблеми в додатку, оскільки оригінальна схема бази даних не містила ПЕРШИХ КЛЮЧІВ у деяких таблицях. Тому, будь ласка, не дозволяйте іншим людям страждати через ваш поганий дизайн. Завжди добре мати первинні ключі на столах.


2

У мене завжди є первинний ключ, навіть якщо на початку я ще не маю на увазі цілі для цього. Було кілька разів, коли мені в кінцевому підсумку потрібна ПК у таблиці, у якої немає такої, і завжди більше проблем скласти її згодом. Я думаю, що більше можливостей завжди включати один.


1

Словом, ні. Однак вам потрібно мати на увазі, що певні операції з клієнтським доступом до CRUD вимагають цього. Для подальшої перевірки я прагну завжди використовувати первинні ключі.


1

Якщо ви використовуєте Hibernate, неможливо створити об'єкт без первинного ключа. Ці проблеми можуть створити проблему, якщо ви працюєте з існуючою базою даних, створеною за допомогою простого сценарію sql / ddl, і не було додано первинного ключа

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.