Цілісність реляційних даних
У другій частині реляційної моделі даних визначаються два обмеження, які повинні виконуватися в будь-якій реляційній базі даних. Це:
Цілісність сутностей
Цілісність зовнішніх ключів.
Перш, ніж говорити про цілісність сутностей, опишемо використовування null-значень в реляційних базах даних.
Null-значення
Основне призначення баз даних полягає в тому, щоб зберігати і надавати інформацію про реальний світ. Для представлення цієї інформації в базі даних використовуються звичні для програмістів типи даних - рядкові, чисельні, логічні і т.п. Проте в реальному світі часто зустрічається ситуація, коли дані невідомі або не повні. Наприклад, місце проживання або дата народження людини можуть бути невідомі (база даних розшукуваних злочинців). Якщо замість невідомої адреси доречно б був вводити порожній рядок, то що вводити замість невідомої дати? Відповідь - порожню дату - не цілком задовільний, оскільки найпростіший запит "видати список людей в порядку зростання дат народження" дасть явно неправильних відповідь.
Для того, щоб обійти проблему неповних або невідомих даних, в базах даних можуть використовуватися типи даних, поповнені так званим null-значенням. Null-значення - це, власне, не значення, а якийсь маркер, що показує, що значення невідоме.
Таким чином, за ситуації, коли можлива поява невідомих або неповних даних, розробник має на вибір два варіанти.
Перший варіант полягає в тому, щоб обмежитися використовуванням звичних типів даних і не використати null-значення, а замість невідомих даних вводити або нульові значення, або значення спеціального вигляду - наприклад, домовитися, що рядок "АДРЕСА НЕВІДОМА" і є ті дані, які потрібно вводити замість невідомої адреси. У будь-якому випадку на користувача (або на розробника) лягає відповідальність на правильне трактування таких даних. Зокрема, може бути потрібно написання спеціального програмного коду, який в потрібних випадках "виловлював" би такі дані. Проблеми, що виникають при цьому очевидні - не всі дані стають рівноправні, потрібен додатковий програмний код, що "відстежує" цю нерівноправність, внаслідок чого ускладнюється розробка і супровід додатків.
Другий варіант полягає у використовуванні null-значень замість невідомих даних. За уявною природністю такого підходу ховаються менш очевидні і більш глибокі проблеми. Самою впадаючою в очі проблемою є необхідність використовування тризначної логіки при операції з даними, які можуть містити null-значення. В цьому випадку при неакуратному формулюванні запитів, навіть найприродніші запити можуть давати неправильні відповіді. Є більш фундаментальні проблеми, пов'язані з теоретичним обгрунтовуванням коректності введення null-значень, наприклад, незрозуміло взагалі, чи входять null-значення в домени чи ні.
Докладне обговорення проблем використовування null-значень виходить за межі даної роботи. Можна тільки сказати про те, що це питання в теорії реляційних баз даних остаточно не вирішено. Основоположник реляційного підходу Кодд рахував null-значення невід'ємною частиною реляційної моделі. К.Дейт, один з найбільших теоретиків реляційної моделі виступає категорично проти null-значень (докладне обговорення проблем, що виникають при використовуванні null-значень приведено в книзі [11].
Практично всі реалізації сучасних реляційних СУБД дозволяють використовувати null-значення, не дивлячись на їх недостатню теоретичну обгрунтованість. Таку ситуацію можна порівняти з ситуацією, що склалася на початку століття з теорією множин. Майже відразу після створення Кантором теорії множин, в ній були знайдені внутрішні суперечності (антиномії). Були розроблені більш строгі теорії, що дозволяють уникнути цих суперечностей (конструктивна теорія множин). Проте в реальній роботі більшість математиків користується класичною теорією множин, оскільки більш строгі теорії більш обмежені і негнучкі у вживанні саме через свою більшу строгість.
Думка автора (дуже скромне в порівнянні з думкою корифеїв реляційної теорії) полягає в тому, що бажано уникати null-значень. Проте, приведемо тут опис тризначної логіки, необхідної для роботи з null-значеннями.
Тризначна логіка (3VL)
Оскільки null-значення позначає насправді той факт, що значення невідоме, то будь-які операції (складання, множення, конкатенація рядків і т.д.) алгебри повинні давати також невідоме значення, тобто null. Дійсно, якщо, наприклад, вага деталі невідома, то невідомо також, скільки важать 10 таких деталей.
При порівнянні виразів, що містять null-значення, результат також може бути невідомий, наприклад, значення істинності для виразу є null, якщо один або обидва аргументи є null. Таким чином, визначення істинності логічних виразів базується на тризначній логіці (three-valued logic, 3VL), в якій окрім значень T, - ІСТИНА і F - БРЕХНЯ, введено значення U - НЕВІДОМО. Логічне значення U - це те ж саме, що і null-значення. Тризначна логіка базується на наступних таблицях істинності:
AND | F | T | U
F | F | F | F
T | F | T | U
U | F | U | U
Таблиця 1 Таблиця істинності AND
OR | F | T | U
F | F | T | U
T | T | T | T
U | U | T | U
Таблиця 2 Таблиця істинності OR
NOT
F | T
T | F
U | U
Таблиця 3 Таблиця істинності NOT
Є декілька парадоксальних наслідків вживання тризначної логіки.
Парадокс 1. Null-значення не рівне самому собі. Дійсно, вираз null = null дає значення не ІСТИНА, а НЕВІДОМО. Значить вираз не обов'язково ІСТИНА!
Парадокс 2. Невірно також, що null-значення не рівне самому собі! Дійсно, вираз nullnull також приймає значення не ІСТИНА, а НЕВІДОМО! Значить також, що і вираз теж не обов'язково БРЕХНЯ!
Парадокс 3. не обов'язково ІСТИНА. Значить, в тризначній логіці не працює принцип виключеного третього (будь-який вислів або істинний, або помилковий).
Таких парадоксів можна побудувати скільки завгодно. Звичайно, це насправді не парадокси, а просто слідства з аксіом тризначної логіки.
Потенційні ключі
За визначенням, тіло відношення є безліч кортежів,