Чи повинен первинний ключ бути незмінним?


26

Недавній питання про StackOverflow викликав дискусію про незмінність первинних ключів. Я думав, що це якесь правило, що первинні ключі повинні бути незмінні. Якщо є ймовірність, що одного дня первинний ключ буде оновлений, я подумав, що вам слід використовувати сурогатний ключ. Однак це не в стандарті SQL, і деякі функції "каскадного оновлення" RDBMS дозволяють змінити первинний ключ.

Отже, моє запитання: чи все-таки погана практика мати первинний ключ, який може змінитися? Які є наслідки наявності первинного ключа, що змінюється?

Відповіді:


25

Ви тільки потрібен первинний ключ , щоб бути незмінні , якщо це пов'язано із зовнішнім ключем, або , якщо він використовується в якості ідентифікатора поза базою даних (наприклад , в URL , який вказує на сторінку для елемента).

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


7
Чому вам потрібно, щоб первинний ключ був непорушним, якщо він пов'язаний із зовнішнім ключем? Як зазначалося в ОП, більшість RDBMS мають функцію "каскаду" оновлення.
Танатос

1
@Thanatos більшість (насправді все, з чим я стикався), rdbms не дозволить змінювати первинні ключі, але ще не має каскадних оновлень. Первинний ключ, в загальноприйнятій мудрості dba, не повинен містити інформації, бути лише унікальним ідентифікатором запису (тому навіть не відмічено часову позначку, діапазон записів, відкладений від нього тощо).
jwenting

5
@jwenting: Ми говоримо про те саме? "більшість rdbms не дозволяють змінювати первинні ключі", що включає? MySQL і PostgreSQL дозволяють змінювати первинні ключі і чекати каскадні оновлення ... як я думаю, стандартний SQL каже, що вони повинні. Також "загальноприйнята мудрість dba"? Я зустрічав безліч мітингувальних груп, які сперечаються з сурогатними ключами, і безліч тих, хто сперечається проти природних ключів.
Танатос

2
@Thanatos Аргументи на користь "всі таблиці повинні мати сурогат" відсутні бібліографічні посилання, вони цитують "загальновизнану мудрість dba", але вони ніколи не цитують книгу. Канонічні книги стверджують, що слід використовувати сурогат, якщо: A. немає природного ключа, B. багатокольоровий ключ перевищує 3 стовпці, або, C. Ви будете постійно змінювати ключ. Отже: природні, коли вони підходять, сурогати, коли природні не підходять.
Тулен Кордова

4
@ user61852: Що?
Гуффа

15

Первинний ключ повинен складатися з усіх необхідних кортежів для визначення унікальності. Чи можуть дані змінюватися чи ні, не має значення. Має значення лише унікальність запису. Це концептуальна конструкція бази даних.

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


15

Так, на мою думку, первинний ключ повинен бути незмінним.

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


Хороший момент про помилки введення даних
Тім Гудман

richeym, здається, ви робите випадок, чому ключі НЕ повинні бути незмінними: користувачі можуть захотіти їх змінити.
nvogel

4
@dportas - моя думка в тому, що мені подобається, щоб ПК не змінювався, тому завжди використовуйте сурогатні ключі, навіть якщо я думаю, що є очевидний ключ, який можна отримати з даних таблиці (наприклад, електронна пошта, ім’я користувача).
richeym

2

Механізми кешування між базою даних та користувачем втратять ефективність, якщо зміниться первинні ключі.


2

Чому ні? Тому що ви хочете усунути стовпчик?

Тільки тому, що вимоги вимагають, щоб три стовпці були унікальними, це не означає, що він повинен бути первинним ключем. Ви можете подумати, що це правило збережеться назавжди (Пам'ятайте, під час тієї зустрічі, коли керівник відділу закруток присягав, що ніколи не зміниться? Ви знаєте, того, що щойно звільнили.), Але це не буде.

Мені не платять за кожне впроваджене оновлення каскаду і бонус, якщо я його кодую сам.

Комп'ютер не вимагає ніякого значення для ключа; ІМХО, ключі призначені для комп'ютерів, нехай люди накручують решту даних.


1
"ключі призначені для комп'ютерів. Нехай люди накручують решту даних." +1, приємно.

2

Непогана практика мати ключ, значення якого може змінюватися.

Властивості хорошого ключа включають стабільність. Незмінність ідеальна, але не обов'язкова умова. Введення штучного ключа заради непорушності - це погана практика.

Візьмемо для прикладу Міжнародний стандартний номер книги (ISBN) . Це дуже стабільно, але непорушно: колись книговидавці роблять помилки і - жах! - можуть виникнути дублікати номерів ISBN Чи означає це, що ISBN не слід сприймати як ключ-кандидат у комп'ютеризованій базі даних? Звичайно, ні. Однією з переваг ISBN є те, що він має надійне джерело, яке вирішить проблеми для всіх користувачів у всьому світі.

Існують і інші властивості хорошого ключа ISBN, що безглуздий цілочисельний ключ, що збільшується автоматично, наприклад, знайомство (кожен, хто в книжковій торгівлі знає або знайомий з ISBN), перевіряється (ISBN друкується на всіх сучасних книгах), може має бути підтверджено з посиланням на СУБД (ISBN має фіксовану ширину і включає контрольну суму) тощо.


3
ISBN має фіксовану ширину, за винятком випадків, коли його немає (див. ISBN-10 проти ISBN-13).
CVn

То як би ви рекомендували обробляти дублікати ISBN? У всіх RDBMS, які мені відомі, вам доведеться мати унікальне обмеження на полі, щоб використовувати його як первинний ключ.
Wildcard

1

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


1

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


0

Як вже говорили деякі коментарі, одне рішення - використовувати новий первинний ключ

Наприклад (за прикладом @onedaywhen), скажімо, що існує таблиця " Книги", в якій зберігається список книг, і ми "використовувались" для визначення ISBN в якості основного ключа. Однак деякі автори допустили помилку введення неправильного ISBN, тому вони попросили змінити ISBN, він передбачав наступні завдання:

  • створити новий реєстр у таблиці Книги
  • вкажіть усі посилання від старого ISBN до нового ISBN. (*)
  • І нарешті, видаліть старий реєстр із таблиці Книги.

(*) це може бути тривіально для пошуку всіх посилань на модель бази даних, яка використовує Foreign Keys, але в деяких моделях її відсутні.

Table Books
ISBN  is the primary key
NAME is a simple field.
etc.

Ми змінюємо це як

Table Books
InternalBookId as the primary key
ISBN as a simple field or an indexed field.
NAME is a simple field.
etc.

Де новий InternalBookId навіть міг би бути автономерним значенням.

Мінуси про це:

  • воно додає нове поле, яке використовує більше простору / ресурсу.

  • це може зажадати переписати всю модель.

  • нова модель може бути менш пояснена.

Професіонал

  • Дозволяє вимкнути "первинний ключ".
  • Дозволяє рівномірно скинути або перефабрикувати "первинний ключ", наприклад, змінити "Книги" на "ISBN-13" настільки просто, що можна скинути старіший стовпець і створити новий

Нова таблиця:

Table Books
InternalBookId as the primary key
ISBN13 is a new field.
NAME is a simple field.
etc.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.