Реляційні бази даних не створені для ідеального вирішення цієї ситуації. Ви повинні вирішити, що для вас найважливіше, а потім зробити свої компроміси. У вас кілька цілей:
- Підтримуйте третю нормальну форму
- Підтримуйте референтну цілісність
- Дотримуйтесь обмеження, що кожен рахунок належить або корпорації, або фізичній особі.
- Збережіть можливість простого та безпосереднього отримання даних
Проблема полягає в тому, що деякі з цих цілей конкурують між собою.
Рішення для субтипірування
Ви можете вибрати рішення для підтипу, де ви створюєте супер-тип, який включає як корпорації, так і осіб. Цей супер-тип, ймовірно, має складений ключ природного ключа підтипу плюс атрибут розділення (наприклад customer_type
). Це нормально, що стосується нормалізації, і це дозволяє забезпечити референтну цілісність, а також обмеження, що корпорації та особи взаємно виключають. Проблема полягає в тому, що це ускладнює пошук даних, тому що ви завжди повинні мати відділення залежно від того, customer_type
коли ви приєднаєтесь до облікового запису до власника облікового запису. Це, ймовірно, означає, UNION
що у вашому запиті використовується багато повторюваних SQL.
Вирішення двох іноземних ключів
Ви можете обрати рішення, коли ви зберігаєте два зовнішніх ключі в таблиці рахунків, один - корпорації та один - особі. Це рішення також дозволяє підтримувати референтну цілісність, нормалізацію та взаємну ексклюзивність. Він також має той самий недолік пошуку даних, що і рішення для підтипу. Насправді це рішення так само, як і рішення про підгрупування, за винятком того, що ви стикаєтеся до проблеми розгалуження вашої логіки приєднання «швидше».
Тим не менш, багато модельєрів даних вважають, що це рішення поступається рішенню для підтипу через те, як застосовується взаємне обмеження виключності. У рішенні про субтипізацію ви використовуєте клавіші для забезпечення взаємної ексклюзивності. У двох рішеннях іноземного ключа ви використовуєте CHECK
обмеження. Я знаю деяких людей, які мають необгрунтовану упередженість щодо обмежень перевірки. Ці люди вважають за краще рішення, яке зберігає обмеження в ключах.
Рішення атрибутів розділення атрибутів "денормалізованого"
Є ще один варіант, коли ви зберігаєте один стовпець із зовнішнім ключем у таблиці рахунків рахунків і використовуєте інший стовпець, щоб повідомити, як інтерпретувати стовпчик із іноземним ключем (RoKa'sOwnerTypeID
стовпчик). Це по суті виключає таблицю супер-типу в рішенні для підтипу, денормалізуючи атрибут розділення на дочірню таблицю. (Зауважте, що це не є строго "денормалізацією" згідно з формальним визначенням, оскільки атрибут розділення є частиною первинного ключа.) Це рішення здається досить простим, оскільки дозволяє уникнути наявності додаткової таблиці, щоб зробити більш-менш те ж саме, і це скорочує кількість стовпців іноземних ключів до одиниці. Проблема цього рішення полягає в тому, що воно не дозволяє уникнути розгалуження логіки пошуку і, крім того, не дозволяє підтримувати декларативну референтну цілісність. Бази даних SQL не мають можливості керувати одним стовпчиком із зовнішнім ключем для однієї з кількох батьківських таблиць.
Спільне рішення домену основного ключа
Один із способів, яким люди іноді займаються цим питанням, - це використовувати єдиний пул ідентифікаторів, щоб не було плутанини для будь-якого даного ідентифікатора, належить він до того чи іншого підтипу. Це, мабуть, спрацює досить природно за банківським сценарієм, оскільки ви не збираєтесь видавати один і той же номер банківського рахунку як корпорації, так і фізичній особі. Це має перевагу у тому, щоб уникнути необхідності в атрибуті розділення. Ви можете зробити це з таблицею супер-типу або без неї. Використання таблиці супер-типу дозволяє використовувати декларативні обмеження для забезпечення унікальності. В іншому випадку це повинно бути здійснено процедурно. Це рішення нормалізовано, але воно не дозволить вам підтримувати декларативну референтну цілісність, якщо ви не зберігаєте таблицю супер-типу. Це все ще не робить нічого, щоб уникнути складної логіки пошуку.
Отже, ви бачите, що не вдається мати чітку конструкцію, яка б відповідала всім правилам, і в той же час простоту пошуку даних. Ви повинні вирішити, де будуть ваші компроміси.
OwnerTypeID
вChecquingAccount
таблиці, з1=Corporation
і2=NaturalPerson
? Таким чином, вам потрібен лише одинOwnerID
уChecquingAccount
таблиці, який ви можете індексувати разом ізOwnerTypeID
.