Чи повинна кожна таблиця мати сурогат / штучний первинний ключ з одним полем?


33

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

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

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


Відповіді:


28

Я скажу ні, не завжди, але більшість часу так. .

Ось деякі обставини, за яких вам не потрібен сурогат чи штучний ключ:

  • Чисті таблиці перетину . Якщо немає ризику перетину стати ціллю стороннього ключа, і якщо ризик перетину є малим або зовсім не залучає незалежні атрибути (тобто щось інше, ніж FK, до двох батьківських таблиць), то ви можете піти з допомогою комбінації ФК як ПК у справедливій впевненості.
  • Таблиці пошуку зі статичними ключами бізнесу . Якщо у вас є пошук
    таблиця з унікальним бізнес-ключем, який закріплений зовні у вашому
    бізнесі і який має нульовий шанс колись змінитись для будь-яких
    практичних цілей, то безпосередньо за допомогою бізнес-ключа можна зробити
    простіше. Прикладом може бути список
    кодів штату чи провінції або список стандартних номерів ANSI тощо.
  • Таблиці, що містять дані, консолідовані з декількох незалежних джерел . Якщо у вашій системі є багато джерел даних, які потрібно об'єднати в єдину таблицю, скажімо, в головному офісі, то іноді вам потрібен складений ключ, який включає значення ключового джерела системи та код, який вказує, що було джерельною системою.

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

  • Ситуації, коли потрібно об'єднати дані з декількох незалежних джерел. Щоб уникнути зіткнення ключів, ви можете використовувати GUID замість ідентифікаційних ключів.
  • Ситуації, коли вас змушують використовувати нечислові представлення ключів. Скажімо, у вас є база даних номерних знаків. Вашим ключем може бути буквено-цифрове значення замість чистого числа.
  • Ситуації, коли якась зовнішня вимога змушує вас застосувати стиснення до вашого ключового значення. Замість використання 10 цифр для int32 ви можете використовувати шість базових 36 цифр.

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

Сказавши це, пам’ятайте, що YAGNI має місце у застосуванні цієї концепції. Вам не потрібно примушувати кодові таблиці з ключами ІДЕНТИЧНОСТІ в кожний куточок вашої схеми, на випадок, якщо хтось вирішить, що символ чоловічої статі у вашій таблиці співробітників повинен змінитися з M на X або щось нерозумно.


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

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

Я не змінив питання, як ви бачите з історії, просто додав наголос, де я думав, що це допоможе непрочитаним читачам
Джек Дуглас

12

Ні.

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

Я спробую проілюструвати свою думку на наступних прикладах, де:

  • brand - автомобільна марка, наприклад, Ford, Toyota тощо
  • dealer - це фізичний дилер, прив’язаний до торгової марки (наприклад, дилер Ford, який продає лише Fords)
  • model - тип автомобіля, наприклад, Ford Focus, Ford Fiesta тощо
  • stock є поточним числом автомобілів передньої площі для кожного дилера

Якщо ми створимо сурогатний ключ з одним полем dealerі для modelнаступного:

create table brand( brand_id integer primary key );

create table dealer( dealer_id integer primary key, 
                     brand_id integer references brand )

create table model( model_id integer primary key, 
                    brand_id integer references brand )

create table stock( model_id integer references model, 
                    dealer_id integer references dealer, 
                    quantity integer,
                      primary key(model_id, dealer_id) )

тоді можна вставити рядок, stockщо посилається на Forddealer з моделлю "Toyota". Додавання brand_id references brandдо stockтільки посилює проблему. З іншого боку, якщо ми збережемо зовнішній ключ як частину первинного ключа, наступним чином:

create table brand( brand_id integer primary key );

create table dealer( brand_id integer references brand, 
                     dealer_id integer, 
                       primary key(brand_id, dealer_id) )

create table model( brand_id integer references brand, 
                    model_id integer, 
                      primary key(brand_id, model_id) )

create table stock( brand_id integer, 
                    model_id integer, 
                    dealer_id integer, 
                    quantity integer,
                      primary key(brand_id, model_id, dealer_id),
                      foreign key(brand_id, model_id) references model,
                      foreign key(brand_id, dealer_id) references dealer )

Тепер правило, що дилери "Форда" можуть запасатися лише автомобілями "Форд", природно моделюється.

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

create table dealer( brand_id integer references brand, 
                     dealer_id serial unique, 
                       primary key(brand_id, dealer_id) )

3
Здійснюючи припущення до звичайних положень щодо прикладів, не обов'язково ідеальних з усіх кутів, я б сказав, що такий тип дизайну є особливо крихким. Незважаючи на те, що можна знайти спосіб використання DRI для виконання бізнес-правил, це також забирає частину вашої здатності реагувати на зміни. Якщо Toyota купує Ford, або навіть якщо дилер Ford вирішує продати вживану Toyota, ваші ділові правила, які керуються DRI, дадуть вам головний біль у технічному обслуговуванні.
Джоел Браун

1
Тож "правила вашого бізнесу можуть змінитися". Це стосується будь-якого правила ведення бізнесу, і його завжди буде важко переробити. Зазвичай мені кажуть, що таке бізнес-правила - я не вирішую їх для себе.
Джек Дуглас

1
Ви говорите, DRI взагалі не слід застосовувати для дотримання правил бізнесу? Хіба це не єдине, що робить DRI? - навіть прості закордонні ключі - це ділові правила, що застосовуються DRI.
Джек Дуглас

4
Звичайно, DRI виконує правила ведення бізнесу. Ви повинні вирішити, які правила будуть виконуватись у коді та які у вашій схемі. Зміни схем майже завжди складніше, ніж зміни коду. Існує два види бізнес-правил, які можуть входити у вашу модель даних. Одна належить там, а одна ні. Принциповий характер важливих для вашого бізнесу даних не сильно змінюється. Конкретні способи роботи з цими даними набагато менші . Правило, як автомобілі мають виробника, належить до моделі даних. Таке правило, як дилери ніколи не продаватимуть дві марки автомобілів, не означає.
Джоел Браун

4
"Зміни схем майже завжди складніше, ніж зміни коду" IMO - навпаки. Насправді я не погоджуюся з практично всім, що ви сказали, але я сумніваюся, що є якийсь аргумент, щоб сперечатися з вами, тому я залишу це на цьому.
Джек Дуглас

12

"це залежить"

Так: Сурогатні поля ІДЕНТИЧНОСТІ / АВТОМОБІЛЬНІ хороші, коли природний ключ широкий і нечисловий. Примітка. Це передбачає співвідношення "PK" та кластерного індексу, яке відбувається за замовчуванням у SQL Server та Sybase тощо

Ні: багато / багато таблиць, коли достатньо двох батьківських клавіш. Або коли природний ключ короткий і фіксованої довжини, наприклад, код валюти

Звичайно, ORM, що подумав про голову (читати: (n) в сплячому режимі), може дотримати ці правила ...

Редагувати: знову читати питання

Таблиця безлічі / багатьох із 2 сурогатними батьківськими ключами матиме PK з декількома стовпцями.
Однак він не потребує іншого сурогатного стовпчика.

Якщо в таблиці є ключ із сурогату (ІДЕНТИЧНОСТІ тощо), тоді він не повинен бути декількома стовпцями.

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

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