Professional Documents
Culture Documents
База Даних (Бд, Database, Db) - Впорядкований Набір Логічно Взаємопов'Язаних
База Даних (Бд, Database, Db) - Впорядкований Набір Логічно Взаємопов'Язаних
База даних (БД, DataBase, DB) — впорядкований набір логічно взаємопов'язаних даних,
що використовуються спільно та призначені для задоволення інформаційних
потреб користувачів. У технічному розумінні включно й система керування БД.
Класифікація по вмісту
- Географічна
- історична
- наукова
- мультимедійна
- Клієнтська.
За ступенем розподіленості
Централізована, або зосереджена (centralized database ): БД , повністю підтримувана на
одному комп'ютері.
Розподілена (distributed database): БД, складові частини якої розміщуються в різних вузлах
комп'ютерної мережі відповідно з яким-небудь критерієм .
Неоднорідна (heterogeneous distributed database): фрагменти розподіленої БД в різних
вузлах мережі підтримуються засобами більше однієї СУБД
Однорідна (homogeneous distributed database): фрагменти розподіленої БД в різних вузлах
мережі підтримуються засобами однієї і тієї ж СУБД.
Фрагментована, або секціонірованная (partitioned database): методом розподілу даних є
фрагментованість (партіціонірованіе, секціонування), вертикальне чи горизонтальне.
Тиражована (replicated database): методом розподілу даних є тиражування ( реплікація ) .
Файл- серверні
У файл- серверних СУБД файли даних розташовуються централізовано на файл- сервері.
СУБД розташовується на кожному клієнтському комп'ютері ( робочої станції). Доступ СУБД
до даних здійснюється через локальну мережу. Синхронізація читань і оновлень
здійснюється за допомогою файлових блокувань.
Перевагою цієї архітектури є низьке навантаження на процесор файлового сервера.
Недоліки: потенційно високе завантаження локальної мережі; ускладненість або
неможливість централізованого управління; ускладненість або неможливість забезпечення
таких важливих характеристик як висока надійність, висока доступність і висока безпека .
Застосовуються найчастіше в локальних додатках, які використовують функції управління
БД; в системах з низькою інтенсивністю обробки даних і низькими піковими
навантаженнями на БД.
На даний момент файл-серверна технологія вважається застарілою, а її використання у
великих інформаційних системах - недоліком.
Приклади: Microsoft Access , Paradox , dBase , FoxPro , Visual FoxPro .
Клієнт – серверні
Клієнт -серверна СУБД розташовується на сервері разом з БД і здійснює доступ до БД
безпосередньо , в монопольному режимі. Всі клієнтські запити на обробку даних
обробляються клієнт- серверної СУБД централізовано.
Недолік клієнт- серверних СУБД полягає в підвищених вимогах до сервера.
Переваги: потенційно більш низьке завантаження локальної мережі; зручність
централізованого управління ; зручність забезпечення таких важливих характеристик як
висока надійність , висока доступність і висока безпека .
Приклади: Oracle , Firebird , Interbase , IBM DB2 , Informix , MS SQL Server , Sybase Adaptive
Server Enterprise , PostgreSQL , MySQL , Caché , Лінтер .
Вбудовувані
Вбудована СУБД - СУБД, яка може поставлятися як складова частина деякого програмного
продукту, не вимагаючи процедури самостійної установки.
Призначена для локального зберігання даних свого додатку і не розрахована на колективне
використання в мережі.
Фізично вбудовується СУБД найчастіше реалізована у вигляді підключається бібліотеки.
Доступ до даних з боку додатка може відбуватися через SQL або через спеціальні програмні
інтерфейси.
Приклади: OpenEdge , SQLite , BerkeleyDB , Firebird Embedded , Microsoft SQL Server
Compact, Лінтер .
Архітектура СКБД
Існує трирівнева система організації СКБД ANSI-SPARC, при якій існує незалежний рівень
для ізоляції програми від особливостей представлення даних на нижчому рівні.
Рівні:
1. Зовнішній — представлення БД з точки зору користувача.
2. Концептуальний — узагальнене представлення БД, описує які дані зберігаються в
БД і зв'язки між ними. Підтримує зовнішні представлення, підтримується внутрішнім
рівнем.
3. Внутрішній — фізичне представлення БД в комп'ютері.
Логічна незалежність — повна захищеність зовнішніх моделей від змін, що вносяться в
концептуальну модель.
Фізична незалежність — захищеність концептуальної моделі від змін, які вносяться у
внутрішню модель.
Рис. 1.1. Трирівнева модель системи управління базою даних, запропонована ANSI
1. Рівень зовнішніх моделей - самий верхній рівень, де кожна модель має своє "бачення"
даних. Цей рівень визначає точку зору на БД окремих застосувань. Кожне застосування
бачить і обробляє тільки ті дані, які необхідні саме цьому застосуванню. Наприклад, система
розподілу робіт використовує зведення про кваліфікацію співробітника, але її не цікавлять
відомості про оклад, домашню адресу і телефон співробітника, і навпаки, саме ці відомості
використовуються в підсистемі відділу кадрів.
2. Концептуальний рівень - центральна ланка, що управляє, тут база даних
представлена в найбільш загальному вигляді, який об'єднує дані, використовувані всіма
застосуваннями, що працюють з даною базою даних. Фактично концептуальний рівень
відображає узагальнену модель наочної області (об'єктів реального миру), для якої
створювалася база даних. Як будь-яка модель, концептуальна модель відображає тільки
істотні, з погляду обробки, особливості об'єктів реального миру.
3. Фізичний рівень - власне дані, розташовані у файлах або в сторінкових структурах,
розташованих на зовнішніх носіях інформації.
Ця архітектура дозволяє забезпечити логічну (між рівнями 1 і 2) і фізичну (між рівнями 2
і 3) незалежність при роботі з даними. Логічна незалежність припускає можливість зміни
одного застосування без коректування інших застосувань, що працюють з цією ж базою
даних. Фізична незалежність припускає можливість перенесення інформації, що
зберігається, з одних носіїв на інших при збереженні працездатності всіх застосувань, що
працюють з даною базою даних. Це саме те, чого не вистачало при використанні файлових
систем.
Виділення концептуального рівня дозволило розробити апарат централізованого
управління базою даних.
Життєвий цикл бази даних - це сукупність етапів, які проходить база даних на своєму
шляху від створення до закінчення використання.
1. Дослідження та аналіз проблеми , для вирішення якої створюється база даних.
2. Побудова інфологічну і даталогіческую моделі .
3. Нормалізація отриманих інфологічну і даталогіческую моделей. По закінченні цього
етапу, як правило отримують заготовки таблиці БД і набір зв'язків між ними (первинні та
вторинні ключі )
4. Перевірка цілісності БД
5. Вибір фізичного способу зберігання та експлуатації (тех. засобу ) бази даних .
6. Проектування вхідних і вихідних форм .
7. Розробка інтерфейсу програми.
8. Функціональне наповнення додатки
9. Налагодження: перевірка на коректність роботи функціонального наповнення системи
10. Тестування: тест на коректність введення виведення даних , тест на максимальну
кількість активних сесій і т. д.
11. Введення в експлуатацію: налагодження ІТ-інфраструктури, навчання користувачів та
ІТ- персоналу.
12. Виведення з експлуатації: перенесення даних в нову СУБД.
Цілісність бази даних (database integrity) - відповідність наявної в базі даних інформації
її внутрішній логіці, структурі і всім явно заданими правилами.
Кожне правило, оскiльки воно має деяке обмеження на можливий стан бази даних,
називається обмеженням цілісності (integrity constraint ).
Приклади правил: вага деталі повинен бути позитивним ; кількість знаків в телефонному
номері не повинно перевищувати 25 ; вік батьків не може бути менше віку їх біологічної
дитини і т.д.
Завдання аналітика і проектувальника бази даних - можливо більш повно виявити всі
наявні обмеження цілісності і задати їх в базі даних.
Цілісність БД не гарантує достовірності інформації, але забезпечує принаймні
правдоподібність цієї інформації, відкидаючи свідомо неймовірні, неможливі значення.
Не слід плутати цілісність БД з достовірністю БД. Достовірність (або істинність) є
відповідність фактів, що зберігаються в базі даних, реальному світу. Очевидно, що для
визначення достовірності БД потрібно володіння повними знаннями як про вміст БД, так і
про реальний світ. Для визначення цілісності БД потрібно лише володіння знаннями про
вміст БД і про задані для неї правилах. Тому СУБД може (і повинна) контролювати цілісність
БД, але принципово не в змозі контролювати достовірність БД. Контроль достовірності БД
може бути покладено тільки на людину , та й то в обмежених масштабах , оскільки в ряді
випадків люди теж не мають повноти знань про реальний світ .
В даний час для структурованих баз даних розрізняють трьох основних типів логічних
моделей даних залежно від характеру підтримуваних ними зв'язків між елементами даних -
мережеву, ієрархічну і реляційну. Класифікуючими ознаками в цих моделях є: ступінь
жорсткості (фіксації) зв'язку, математичне представлення структури моделі і допустимі типи
даних (див. таблицю 1.1). Допустимі типи даних обговорюватимуться далі при вивченні
реляційної моделі.
У багатьох випадках для розробників ІС буває поважно ділення СУБД (і БД) по характеру
обробки: на централізованих і розподілених.
Ієрархічна модель
Ієрархічна модель даних організовує дані у вигляді деревовидної структури і є реалізацією
логічних зв'язків між даними типу родових стосунків або стосунків "частинне-ціле".
Прикладом простого ієрархічного уявлення може служити адміністративна структура
організації.
Особливістю такого представлення даних є наявність декількох підлеглих рівнів. У
ієрархічній моделі є кореневий вузол або корінь дерева. Він розташовується на 1-му,
найвищому рівні і не має вузлів-попередників. Решта вузлів називається породженими і
зв'язані між собою таким чином: кожен вузол має початковий, такий, що знаходиться на
вищестоящому рівні. На наступному рівні кожен вузол може мати більш за один вузол-
нащадок або не мати нащадків зовсім. Вузли, що не мають породжених, називаються
листям. У ієрархії розглядують рівні, на яких розташований той або інший вузол або
сукупність вузлів.
Між початковим вузлом і породженими вузлами по умові моделі існує зв'язок "один-ко-
многим" (або "многие-к-одному").
Припустимо, що кожен викладач може читати декілька дисциплін, а кожен студент також
може вивчати декілька дисциплін.
Один з можливих варіантів побудови ієрархічної моделі може бути таким. Кореневим вузлом
є студент (Номер студента, ФІО, Номер групи). Для кожного студента при даному уявленні
є екземпляр кореневого вузла. Викладач і дисципліна об'єднуються в один породжений
вузол (Табельний номер викладача, ФІО, Вчене звання, Кафедра, Дисципліна, Дата іспиту,
Оцінка, Залік).
При такій організації даних достатньо легко отримувати відповіді на запити типу "видати
інформацію про складання іспитів студентами по різних дисциплінах". Проте при відповіді
на питання, які викладачі приймають іспити по ВТ, необхідно проглянути всі записи
породжених вузлів для кожного кореневого вузла. Для цього питання більш підходить
модель, в якій кореневим вузлом є викладач (Табельний номер викладача, ФІО, вчене
звання, кафедра), а породженим є студент (номер студента, ФІО, номер групи, дисципліна,
дата здачі, оцінка, залік).
У першому варіанті моделі для кожного студента дублюється інформація (у екземплярі
породженого вузла) про викладачів і дисципліну, а в другому - для кожного викладача про
студентів. Звідси виникають проблеми включення і видалення даних. З принципу ієрархії
виходить, що екземпляр породженого вузла не може існувати у відсутність відповідного
йому екземпляра початкового вузла. Таким чином, неможливо без залучення додаткових
способів включити в базу даних інформацію про викладачів, які не приймають іспити (для
першого варіанту схеми).
Мережева модель
Зупинимося на понятті мережевої структури, покладеної в основу мережевої моделі даних.
Розгледимо відношення між наступними об'єктами: Студентський колектив, Студентська
група, Кімната в гуртожитку і Студент. Взаємозв'язок між цими об'єктами не є ієрархічним,
оскільки породжений елемент Студент має два початкових - Студентська група і Кімната в
гуртожитку. Такі стосунки, коли породжений елемент має більш одного початкового,
описуються у вигляді мережевої структури. У такій структурі будь-який елемент може бути
пов'язаний з будь-яким іншим елементом.
Що таке XML
XML (eXtensible Markup Language) – це розширювана мова розмітки - стандарт побудови мов
розмітки ієрархічно структурованих даних . Є спрощеною підмножиною мови
розмітки SGML. XML документ складається із текстових знаків, і придатний до читання
людиною.
Тегом (Tag) в XML називається текст, що заключний між в <>. Назви тегів в XML можуть
бути довільними і визначаються автором XML-документу.
Структура документу
XML документ має структуру дерева, починається з корені (root) та має гілки(branch) і
листки (leaf).
Правила синтаксису
Всі xml теги мають мати закриваючий тег
<tag></tag>
<tag/>
Атрибути елементів потрібно завжди брати в лапки і вони мають бути унікальними для
одного елементу
<note date="12/11/2007">
Атрибути
Тег може мітити додаткову інформацію у вигляді атрибутів.
<note date="12/11/2007">
Особливих правил, що має бути тегом, а що атрибутом немає. Наступні три приклади є
еквівалентними
<note date="10/01/2008">
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
<note>
<date>10/01/2008</date>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
<note>
<date>
<day>10</day>
<month>01</month>
<year>2008</year>
</date>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
Використання префіксів
Приклад різних сутностей, які будучи в одному xml-документів призведуть до конфлікту
імен.
<table> <table>
<tr> <name>African Coffee Table</name>
<td>Apples</td> <width>80</width>
<td>Bananas</td> <length>120</length>
</tr> </table>
</table>
<f:table>
<f:name>African Coffee Table</f:name>
<f:width>80</f:width>
<f:length>120</f:length>
</f:table>
При використання префіксів, потрібно задати для них namespace. Задається при
допомозі xmlns атрибуту в першому елементі.
xmlns:prefix="URI".
<root>
<h:table xmlns:h="http://www.w3.org/TR/html4/">
<h:tr>
<h:td>Apples</h:td>
<h:td>Bananas</h:td>
</h:tr>
</h:table>
<f:table xmlns:f="http://www.w3schools.com/furniture">
<f:name>African Coffee Table</f:name>
<f:width>80</f:width>
<f:length>120</f:length>
</f:table>
</root>
<root xmlns:h=http://www.w3.org/TR/html4/
xmlns:f="http://www.w3schools.com/furniture">
<h:table>
<h:tr>
<h:td>Apples</h:td>
<h:td>Bananas</h:td>
</h:tr>
</h:table>
<f:table>
<f:name>African Coffee Table</f:name>
<f:width>80</f:width>
<f:length>120</f:length>
</f:table>
</root>
<!DOCTYPE note
[
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
]>
XML Schema
Аналогом DTD є XML schema, яка в свою чергу теж є xml документом.
<xs:element name="note">
<xs:complexType>
<xs:sequence>
<xs:element name="to" type="xs:string"/>
<xs:element name="from" type="xs:string"/>
<xs:element name="heading" type="xs:string"/>
<xs:element name="body" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
JSON
Викоритсання json:
- написанні javascirpt-застосунків
- серіалізації та пересилання структурованої інформації
- один з основних способів передчі даних від сервера до клієнта у web-застосунках
- Веб-сервіси та API використовують json для представлення даних
- підтримується сучасними мовами програмування та базами даних
Приклад:
{
"book": [
{
"id":"01",
"language": "Java",
"edition": "third",
"author": "Herbert Schildt"
},
{
"id":"07",
"language": "C++",
"edition": "second"
"author": "E.Balagurusamy"
}]
}
JSON Schema
Для перевірки коректності json-документу можна використовувати валідацію цього
документу на відповідність заданій структурі:
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Product",
"description": "A product from Acme's catalog",
"type": "object",
"properties": {
"id": {
"description": "The unique identifier for a product",
"type": "integer"
},
"name": {
"description": "Name of the product",
"type": "string"
},
"price": {
"type": "number",
"minimum": 0,
"exclusiveMinimum": true
}
},
"required": ["id", "name", "price"]
}
Реляційна модель даних
Поняття тип даних в реляційної моделі даних повністю відповідає поняттю типу даних в
мовах програмування. Зазвичай в сучасних реляційних БД допускається зберігання
символьних, числових даних, бітових рядків, спеціалізованих числових даних (таких як
"гроші" ), а також спеціальних " темпоральних " даних ( дата, час, часовий інтервал ). Досить
активно розвивається підхід до розширення можливостей реляційних систем абстрактними
типами даних ( відповідними можливостями володіють, наприклад, системи сімейства Ingres
/ Postgres ). У нашому прикладі ми маємо справу з даними трьох типів: рядки символів, цілі
числа і " гроші".
Поняття домену більш специфічно для баз даних, хоча і має деякі аналогії з підтипами в
деяких мовах програмування. У найзагальнішому вигляді домен визначається заданням
деякого базового типу даних, до якого відносяться елементи домену, і довільного логічного
виразу, який застосовується до елемента типу даних. Якщо обчислення цього логічного виразу
дає результат "істина", то елемент даних є елементом домену.
Найбільш правильною інтуїтивною трактуванням поняття домену є розуміння домену як
допустимої множини значень даного типу. Наприклад, домен " Імена" у нашому прикладі
визначений на базовому типі рядків символів, але в число його значень можуть входити лише
ті рядки, які можуть зображати ім'я (зокрема, такі рядки не можуть починатися з м'якого
знака).
Слід відзначити також семантичне навантаження поняття домену: дані можна порівнювати
тільки в тому випадку, коли вони відносяться до одного домену. У нашому прикладі значення
доменів " Номери пропусків " і " Номери груп " відносяться до типу цілих чисел, але не є
порівнюваними. Зауважимо, що в більшості реляційних СУБД поняття домену не
використовується.
Схема відношення - це іменована множина пар { ім'я атрибута, ім'я домену (або типу, якщо
поняття домену не підтримується) }.
Ступінь або " арність " схеми відношення - потужність цієї множини (кардинальне
число множини). Для скінченної множини A кардинальним числом |A| є натуральне число,
яким позначається кількість елементів цієї множини. Ступінь відношення СПІВРОБІТНИКИ
дорівнює чотирьом, тобто воно є 4- арним. Якщо всі атрибути одного відношення визначені
на різних доменах, осмислено використовувати для іменування атрибутів імена відповідних
доменів.
Кортеж, що відповідає даній схемі відносини, - це множина пар { ім'я атрибута, значення
}, яка містить одне входження кожного імені атрибута, що належить схемі відносини. "
Значення " є допустимим значенням домену даного атрибуту. Тим самим, ступінь або " арність
" кортежу, тобто число елементів у ньому, збігається з " арністю " відповідної схеми
відношення. Попросту кажучи, кортеж - це набір іменованих значень заданого типу.
Віднощення - це множина кортежів, які відповідають одній схемі відношення. Іноді, щоб не
плутатися, говорять "відношення - схема" і "відношення - екземпляр", іноді схему відношення
називають заголовком відношення, а відношення як набір кортежів - тілом відношення.
Насправді, поняття схеми відносини найближче до поняття структурного типу даних в мовах
програмування. Було б цілком логічно дозволяти окремо визначати схему відношення, а потім
одне або декілька відношень за даною схемою.
Однак у реляційних базах даних це не прийнято. Ім'я схеми відношення в таких базах даних
завжди збігається з ім'ям відповідного віднощення - екземпляра. У класичних реляційних
базах даних після визначення схеми бази даних змінюються тільки відношення - екземпляри.
У них можуть з'являтися нові і відалятися або модифікуватися існуючі кортежі. Однак у
багатьох реалізаціях допускається і зміна схеми бази даних: визначення нових та зміна
існуючих схем відношень. Це прийнято називати еволюцією схеми бази даних.
Звичним представленням відношення є таблиця, заголовком якої є схема відношення, а
рядками - кортежі відношення - екземпляра ; в цьому випадку імена атрибутів іменують
стовпці цієї таблиці. Тому іноді кажуть " стовпець таблиці ", маючи на увазі " атрибут
відношення". Цією термінології дотримуються в більшості комерційних реляційних СУБД.
Реляційна база даних - це набір відношень, імена яких збігаються з іменами схем відношень
в схемі БД.
В цілісній частині реляційної моделі даних фіксуються дві базові вимоги цілісності, які
повинні підтримуватися в будь-якої реляційної СУБД.
Перша вимога називається вимогою цілісності сутностей (entity integrity). Об'єкту або
сутності реального світу в реляційних БД відповідають кортежі відношень. Вимога полягає в
тому, що будь-який кортеж будь-якого відношення відрізнити від будь-якого іншого кортежу
цього відношення, тобто іншими словами, будь-яке відношення має володіти первинним
ключем. Ця вимога автоматично задовольняється, якщо в системі не порушуються базові
властивості відношень.
Теоретично будь-який кортеж, що заноситься у відношення, повинен містити всі
характеристики модельованої ним сутності реального світу. Проте на практиці не всі ці
характеристики можуть бути відомі до того моменту, коли ми фіксуємо сутність в базі даних.
Простим прикладом може бути процедура прийняття на роботу людини, розмір заробітної
плати якого ще не визначений. В цьому випадку службовець відділу кадрів, який заносить у
відношення СЛУЖБОВЦІ кортеж, що описує нового службовця, просто не може забезпечити
значення атрибуту Слу_зарп.
Едгар Кодд запропонував використовувати в таких випадках невизначені значення.
Невизначене значення не належить ніякому типу даних і може бути присутнім серед значень
будь-якого атрибуту, визначеного на будь-якому типові даних (якщо це явно не заборонено
при визначенні атрибуту). Якщо а - це значення деякого типа даних або NULL, op - будь-яка
бінарна арифметична операція цього типа даних (наприклад +), а lop - операція порівняння
значень цього типа (наприклад =), то за визначенням:
а op NULL = NULL
NULL op а = NULL
а lop NULL = unknown
NULL lop а = unknown
Тут unknown - це третє значення логічного, або булевого, типа, що володіє наступними
властивостями:
NOT unknown = unknown
true AND unknown = unknown
true OR unknown = true
false AND unknown = false
false OR unknown = unknown
Атрибут такого роду називається зовнішнім ключем (foreign key), оскільки його значення
однозначно характеризують суті, представлені кортежами деякого іншого відношення ( тобто
задають значення їх первинного ключа).
Кажуть, що відношення, в якому визначено зовнішній ключ, посилається на відповідне
відношення, в якому такий же атрибут є первинним ключем.
Вимога цілісності по посиланнях, або вимога зовнішнього ключа полягає в тому, що для
кожного значення зовнішнього ключа, що міститься у одному відношенні, повинен знайтися
кортеж з таким же значенням первинного ключа у відношенні, на яку веде посилання, або
значення зовнішнього ключа повинно бути невизначеним (тобто ні на що не вказувати ). Для
нашого прикладу це означає, що якщо для співробітника вказано номер відділу, то цей відділ
повинен існувати.
Ці механізми володіють однією важливою властивістю: вони замкнені відносно поняття відношення.
Це означає, що вирази реляційної алгебри і формули реляційного числення визначаються над
відношеннями реляційних БД і результатом обчислення також є відношення. В результаті будь-який
вираз або формула можуть інтерпретуватися як відношення, що дозволяє використовувати їх в інших
виразах або формулах.
Алгебра та числення володіють великою виразною потужністю: дуже складні запити до бази даних
можуть бути виражені за допомогою одного виразу реляційної алгебри або однієї формули реляційного
числення. Саме з цієї причини ці механізми включені в реляційну модель даних.
Конкретна мова маніпулювання реляційними БД називається реляційно повною, якщо будь-який
запит, що виражається за допомогою одного виразу реляційної алгебри або однієї формули реляційного
числення, може бути виражена за допомогою одного оператора цієї мови.
Відомо, що механізми реляційної алгебри і реляційного числення еквівалентні, тобто для будь-якого
допустимого вираження реляційної алгебри можна побудувати еквівалентну формулу реляційного
числення і навпаки. Чому ж в реляційній моделі даних присутні обидва ці механізму ?
Справа в тому, що вони розрізняються рівнем процедурності. Вирази реляційної алгебри будуються
на основі алгебраїчних операцій (високого рівня), і подібно до того, як інтерпретуються арифметичні і
логічні вирази, вираз реляційної алгебри також має процедурну інтерпретацію. Іншими словами, запит,
представлений на мові реляційної алгебри, може бути обчислений на основі елементарних
алгебраїчних операцій з урахуванням їх старшинства і наявності дужок. Для формули реляційного
числення однозначна інтерпретація, взагалі кажучи, відсутня. Формула тільки встановлює умови, яким
повинні задовольняти кортежі результуючого відношення. Тому мови реляційного числення є більш
непроцедурними або декларативними.
Оскільки механізми реляційної алгебри і реляційного числення еквівалентні, то в конкретній ситуації
для перевірки ступеня реляційності деякої мови БД можна користуватися будь-яким з цих механізмів.
Зауважимо, що вкрай рідко алгебра або числення приймаються в якості повної основи для мови БД.
Зазвичай (як, наприклад, у випадку мови SQL ) мова грунтується на деякій суміші алгебраїчних і логічних
конструкцій. Проте, знання алгебраїчних і логічних основ мов баз даних часто буває корисно на практиці.
У викладі нижче будемо слідувати підходу Дейта.
Реляційна алгебра
Основна ідея реляційної алгебри полягає в тому, що оскільки відношення є множинами, то засоби
маніпулювання відношенями можуть базуватися на традиційних теоретико -множинних операціях,
доповнених деякими спеціальними операціями, специфічними для баз даних.
Існує багато підходів до визначення реляційної алгебри, які розрізняються набором операцій і
способами їх інтерпретації, але в принципі, більш-менш рівносильні.
Розглянемо розширений початковий варіант алгебри, який був запропонований Коддом (реляційна
алгебра Кодда). У цьому варіанті набір основних алгебраїчних операцій складається з восьми операцій,
які діляться на два класи - теоретико - множинні операції та спеціальні реляційні операції.
До складу теоретико -множинних операцій алгебри Кодда входять операції:
- об'єднання відношень;
- перетину відношень;
- взяття різниці відношень;
- декартовий добуток відношень.
Спеціальні реляційні операції включають:
- обмеження відношень;
- проекцію відношень;
- з’єднання відношень;
- ділення відношень.
Крім того, до складу алгебри включається операція присвоювання, що дозволяє зберегти в базі
даних результати обчислення алгебраїчних виразів, і операція перейменування атрибутів, що дає
можливість коректно сформувати заголовок (схему) результуючого відношення.
Але якщо в теорії множин операція об'єднання осмислена для будь-яких двох множин-операндів, то
у випадку разі реляційної алгебри результатом операції об'єднання має бути відношення. Якщо в
реляційній алгебрі допустити можливість теоретико-множинного об'єднання двох довільних відношень
(з різними заголовками), то, звичайно, результатом операції буде множина, але множина різнотипних
кортежів, тобто не відношень. Якщо виходити з вимоги замкнутості реляційної алгебри щодо поняття
відношення, то така операція об'єднання є безглуздою.
Такі міркування підводять до поняття сумісності відношень по об'єднанню: два відношення сумісні
по об'єднанню в тому і лише у тому випадку, коли володіють однаковими заголовками. У розгорненій
формі це означає, що в заголовках обох відношень міститься один і той же набір імен атрибутів, і
однойменні атрибути визначені на одному і тому ж домені.
Якщо два відношення сумісні по об'єднанню, то при звичайному виконанні над ними операцій
об'єднання, перетину і узяття різниці результатом операції є відношення з коректним заголовком,
співпадаючим із заголовком кожного із відношень-операндів.
Якщо два відношення «майже» сумісні по об'єднанню, тобто сумісні у всьому, окрім імен атрибутів,
то до виконання операції об'єднання ці відношення можна зробити повністю сумісними по об'єднанню
шляхом застосування операції перейменування.
Наприклад операція об'єднання, перетину і узяття різниці припустимо в базі даних є два відношення
Службовці_в_проекті_1 і Службовці_в_проекті_2 з однаковими схемами { Слу_номер, Слу_імя,
Слу_зарп, Слу_отд_номер}. Кожне із відношень містить дані про службовців, що беруть участь у
відповідному проекті.
Відмітимо, що включення до складу операцій реляційної алгебри одразу трьох операцій об'єднання,
перетину і узяття різниці є, очевидно, надлишковим, оскільки, наприклад, операція перетину
виражається через операцію узяття різниці. Проте Кодд свого часу вирішив включити всі три операції,
виходячи з інтуїтивних потреб далекого від математики потенційного користувача системи реляційних
БД.
У теорії множин декартовий добуток (TIMES) може бути отриманий для будь-яких двох множин, і
елементами результуючої множини є пари, складені з елементів першої і другої множин. Якщо говорити
точніше, декартовим добуток множин A{a} і B{b} є така множина пар C{<c1, c2>}, що для кожного
елементу <c1, c2> множини C існує такий елемент а множина A, що c1=a, і такий елемент b множинаі
B, що c2=b.
Оскільки відношення є множинами, для будь-яких двох відношень можливе отримання прямого
добуток. Але результат не буде відношенням. Елементами результату будуть не кортежі, а пари
кортежів.
Тому в реляційній алгебрі використовується спеціалізована форма операції узяття декартового
добуток - розширений декартовий добуток відношень. При узятті розширеного декартового добуток
двох відношень елементом результуючого відношення є кортеж, який є об'єднанням одного кортежу
першого відношення і одного кортежу другого відношення.
Нехай є два відношення R1{a1, a2, …, an} і R2{b1, b2, …, bm}. Тоді результатом операції R1 TIMES R2 є
відношення R{a1, a2, …, an, b1, b2, …, bm}, тіло якого є множина кортежів вигляду {ra1, ra2, …, ran, rb1, rb2, …,
rbm} таких, що {ra1, ra2, …, ran} входить в тіло R1, а {rb1, rb2, …, rbm} входить в тіло R2.
Але тепер виникає друга проблема - як отримати коректно сформований заголовок відношення-
результату? Оскільки схема результуючого відношення є об'єднанням схем відношень-операндів, то
очевидною проблемою може бути іменування атрибутів результуючого відношення, якщо відношення-
операнди володіють однойменними атрибутами.
Ці міркування приводять до введення поняття сумісності по узяттю розширеного декартового
добутоку. Два відношення сумісні по узяттю розширеного декартового добутку в тому і лише в тому
випадку, якщо перетин множин імен атрибутів, узятих з їх схем відношень, порожній. Будь-які два
відношення завжди можуть стати сумісними по узяттю декартового добутку, якщо застосувати операцію
перейменування до одного з цих відношень.
Для ілюстрації використання декартового добутку припустимо, що на додаток до введених раніше
відношень Службовці_в_проекті_1 і Службовці_в_проекті_2 в базі даних міститься ще і відношення
ПРОЕКТИ з схемою { Проєкт_назв, Проєкт_рук} (імена доменів знову опущені). Тоді результат операції
Службовці_в_проекті_1 TIMES ПРОЕКТИ буде:
Слід зауважити, що операція узяття декартового добутку не є дуже осмисленою на практиці. По-
перше, потужність тіла її результату дуже велика навіть при допустимих потужностях операндів, а, по-
друге, результат операції не більш інформативний, ніж узяті в сукупності операнди. Як буде показано
далі, основний сенс включення операції розширеного декартового добутку до складу реляційної
алгебри Кодда полягає в тому, що на її основі визначається дійсно корисна операція з'єднання.
A WHERE comp1 AND comp2 те ж саме, що (A WHERE comp1) INTERSECT (A WHERE comp2)
Для ілюстрації цієї операції припустимо, що в базі даних службовців підтримуються наступні
відношення: СЛУЖБОВЦІ, як воно було визначене раніше, і унарне відношення Номери_проектів {
Про_ном}.
Тоді запит СЛУЖБОВЦІ DIVIDE BY Номери_проектів видасть дані про всіх службовців, що беруть
участь у всіх проектах.
Реляційне числення
Припустимо, що ми працюємо з базою даних, що володіє схемою СПІВРОБІТНИКИ ( СОТР_НОМ,
СОТР_ІМЯ, СОТР_ЗАРП, ОТД_НОМ ) і ВІДДІЛИ ( ОТД_НОМ, ОТД_КОЛ, ОТД_НАЧ ), і хочемо дізнатися
імена та номери співробітників, які є начальниками відділів з кількістю співробітників більше 50.
Якби для формулювання такого запиту використовувалася реляційна алгебра, то ми отримали б
алгебраїчний вираз, який читалося б, наприклад, таким чином:
- виконати зєднання відношень СПІВРОБІТНИКИ і ВІДДІЛИ за умовою СОТР_НОМ = ОТД_НАЧ ;
- обмежити отримане відношення за умовою ОТД_КОЛ > 50 ;
- спроектувати результат попередньої операції на атрибут СОТР_ІМЯ, СОТР_НОМ.
Ми чітко сформулювали послідовність кроків виконання запиту, кожен з яких відповідає одній
реляційної операції. Якщо ж сформулювати той самий запит з використанням реляційного числення, то
ми отримали б формулу, яку можна було б прочитати, наприклад, таким чином:
Повернути СОТР_ІМЯ і СОТР_НОМ для співробітників таких, що існує відділ з таким же значенням
ОТД_НАЧ і значенням ОТД_КОЛ великим 50.
На відміну від реляційної алгебри, при використанні числення необхідно доби римуватися деякого
конкретного синтаксису. Використовуваний синтаксис близький, але не повністю збігається з
синтаксисом мови баз даних QUEL, який довгий час був основною мовою СУБД Ingres.
Для визначення кортежної змінної використовується оператор RANGE. Наприклад, для того, щоб
визначити змінну СПІВРОБІТНИК, областю визначення якої є ставлення СПІВРОБІТНИКИ, потрібно
вжити конструкцію
RANGE СПІВРОБІТНИК IS СПІВРОБІТНИКИ
Правильно побудовані формули ( WFF - Well- Formed Formula ) служать для вираження умов, що
накладаються на кортежних змінні. Основою WFF є прості порівняння ( comparison ), що представляють
собою операції порівняння скалярних значень ( значень атрибутів змінних або літерально заданих
констант ).
Наприклад, конструкція " СОТРУДНІК.СОТР_НОМ = 140 " є простим порівнянням. За визначенням,
просте порівняння є WFF, а WFF, вкладене в круглі дужки, є простим порівнянням.
Більш складні варіанти WFF будуються за допомогою логічних зв'язок NOT, AND, OR і IF... THEN.
Так, якщо form - WFF, а comp - просте порівняння, то NOT form, comp AND form, comp OR form і IF comp
THEN form є WFF.
Нарешті, допускається побудова WFF за допомогою кванторів. Якщо form - це WFF, в якій бере
участь змінна var, то конструкції EXISTS var ( form ) і FORALL var ( form ) представляють wff.
Змінні, що входять до WFF, можуть бути вільними або зв'язаними. Всі змінні, що входять в WFF, при
побудові якої не використовувалися квантори, є вільними. Фактично, це означає, що якщо для якогось
набору значень вільних кортежних змінних при обчисленні WFF отримано значення true, то ці значення
кортежних змінних можуть входити в результуюче відношення. Якщо ж ім'я змінної використано відразу
після квантора при побудові WFF виду EXISTS var ( form ) або FORALL var ( form ), то в цій WFF і у всіх
WFF, побудованих з її участю, var - зв'язана змінна. Це означає, що така змінну не видно за межами
мінімальної WFF, що зв'язала цю змінну. При обчисленні значення такої WFF використовується не одне
значення пов'язаної змінної, а вся її область визначення.
Нехай СОТР1 і СОТР2 - дві кортежних змінні, визначені на відношення СПІВРОБІТНИКИ. Тоді, WFF
EXISTS СОТР2 ( СОТР1.СОТР_ЗАРП > СОТР2.СОТР_ЗАРП ) для поточного кортежу змінної СОТР1
приймає значення true в тому і тільки в тому випадку, якщо в усьому відношенні СПІВРОБІТНИКИ
знайдеться кортеж (пов'язаний із змінною СОТР2 ) такий, що значення його атрибуту СОТР_ЗАРП
задовольняє внутрішньій умові порівняння. WFF FORALL СОТР2 ( СОТР1.СОТР_ЗАРП >
СОТР2.СОТР_ЗАРП ) для поточного кортежу змінної СОТР1 приймає значення true в тому і тільки в
тому випадку, якщо для всіх кортежів відносшення СПІВРОБІТНИКИ ( пов'язаних із змінною СОТР2 )
значення атрибута СОТР_ЗАРП задовольняють умові порівняння.
Легко бачити, що якщо змінна var є пов'язаної в WFF form, то у всіх WFF, що включають дану, може
використовуватися ім'я змінної var, яка може бути вільною або пов'язаної, але в будь-якому випадку не
має ніякого відношення до входження змінної var в WFF form. Ось приклад:
Тут ми маємо два пов'язаних входження змінної СОТР2 з абсолютно різним змістом.
Цільові списки і вирази реляційного числення
Отже, WFF забезпечують засоби формулювання умови вибірки з відношення БД. Щоб можна було
використовувати числення для реальної роботи з БД, потрібно ще один компонент, який визначає набір
і імена стовпців результуючого відносини. Цей компонент називається цільовим списком ( target_list ).
Цільовий список будується з цільових елементів, кожен з яких може мати наступний вигляд:
var.attr, де var - ім'я вільної змінної відповідної WFF, а attr - ім'я атрибута відношення, на якому
визначена змінна var ;
var, що еквівалентно наявності підсписку var.attr1, var.attr2,..., var.attrn, де attr1, attr2,..., attrn включає
імена всіх атрибутів початкового відношення;
new_name = var.attr ; new_name - нове ім'я відповідного атрибута результуючого відношення.
Останній варіант потрібен в тих випадках, коли в WFF використовуються кілька вільних змінних з
однаковою областю визначення.
Результатом реляційного числення кортежів називається конструкція вигляду target_list WHERE wff.
Значенням виразу є відношення, тіло якого визначається WFF, а набір атрибутів і їх імена - цільовим
списком.
Основною формальною відмінністю числення доменів від числення кортежів є наявність додаткового
набору предикатів, що дозволяють формувати так звані умови членства. Якщо R - це n - арне
відношення з атрибутами a1, a2,..., an, то умова членства має вигляд
де vij - це або літерально задана константа, або ім'я кортежної змінної. Умова членства приймає
значення true в тому і тільки в тому випадку, якщо стосовно R існує кортеж, що містить вказані значення
зазначених атрибутів. Якщо vij - константа, то на атрибут aij задається жорстка умова, що не залежить
від поточних значень доменних змінних; якщо ж vij - ім'я доменної змінної, то умова членства може
приймати різні значення при різних значеннях цієї змінної.
У всіх інших відношеннях формули і вирази обчислення доменів виглядають схожими на формули і
вирази обчислення кортежів. Зокрема, розрізняються вільні і пов'язані входження доменних змінних.
Для прикладу сформулюємо з використанням обчислення доменів запит "Видати номери і імена
співробітників, які не отримують мінімальну заробітну плату" (вважатимемо для простоти, що ми
визначили доменні змінні, імена яких збігаються з іменами атрибутів відношення СПІВРОБІТНИКИ, а в
разі, коли потрібно кілька доменних змінних, визначених на одному домені, ми будемо додавати в кінці
імені цифри ):
Реляційне числення доменів є основою більшості мов запитів, заснованих на використанні форм.
Зокрема, на цьому обчисленні базувалася мова Query-by-Example, яка була першою мовою в сімействі
мов, заснованих на табличних формах.
Функціональні залежності
Загальні визначення
Нехай задана змінна відношення r, а X і Y є довільними підмножинами заголовка r
("складеними" атрибутами).
Насправді, для тіла відношення Служащие_проєкти в тому вигляді, в якому воно показане
на мал. 6.1, виконуються ще і наступні FD (1):
СЛУ_НОМ СЛУ_ИМЯ
СЛУ_НОМ СЛУ_ЗАРП
СЛУ_НОМ ПРО_НОМ
СЛУ_НОМ ПРОЕКТ_РУК
{СЛУ_НОМ, СЛУ_ИМЯ} СЛУ_ЗАРП
{СЛУ_НОМ, СЛУ_ИМЯ} ПРО_НОМ
{СЛУ_НОМ, СЛУ_ИМЯ} {СЛУ_ЗАРП, ПРО_НОМ}
…
ПРО_НОМ ПРОЕКТ_РУК и т.д.
СЛУ_ИМЯ СЛУ_НОМ
СЛУ_ИМЯ СЛУ_ЗАРП
СЛУ_ИМЯ ПРО_НОМ и т.д.
СЛУ_ЗАРП ПРО_НОМ
Проте відмітимо, що природа FD групи (1) відрізняється від природи FD груп (2) і (3).
Логічно припустити, що ідентифікаційні номери службовців мають бути завжди різні, а у
кожного проекту є тільки один керівник. Тому FD групи (1) мають бути вірні для будь-якого
допустимого значення змінної відношення Служащие_проєкти і можуть розглядуватися
як інваріанти, або обмеження цілісності для цією змінною відношення.
FD групи (2) базуються на менш природному припущенні про те, що імена всіх службовців
різні. Це відповідає дійсності для прикладу з мал. 6.1, але можливо, що з часом FD групи
(2) не виконуватимуться для якого-небудь значення змінної відношення
Служащие_проєкти.
Надалі нас цікавитимуть тільки ті функціональні залежності, які повинні виконуватися для
всіх можливих значень змінних відношень.
Отже, ми матимемо справу з FD, які виконуються для всіх можливих станів тіла відповідного
відношення і можуть розглядуватися як обмеження цілісності. Як показує (неповний) список
(1), таких залежностей може бути дуже багато. Оскільки вони трактуються як обмеження
цілісності, за їх дотриманням повинна стежити СУБД. Тому важливо уміти скоротити
набір FD до мінімуму, підтримка якого гарантує виконання всіх залежностей. Ми займемося
цим далі.
Спершу наведемо два приклади FD, з яких виходять (або виводяться) інші FD. Знову
користуватимемося відношенням Служащие_проєкти. Для цього відношення виконується,
наприклад, FD Слу_ном { Слу_зарп, Про_ном}. З цієї FD виводяться FD Слу_ном
слу_зарп і Слу_ном про_ном.
1. якщо B A, то A B (рефлексивність);
2. якщо A B, то AC BC (поповнення);
3. якщо A BіB C, то A C (транзитивність).
Алгоритм обчислення Z+ дуже простий. Один з його варіантів показаний на мал. 6.2.
Легко відмітити, що S2 є покриттям S1 тоді і тільки тоді, коли S1+ S2+. Дві множина FD S1
і S2 називаються еквівалентними, якщо кожна з них є покриттям іншого, тобто S1+ = S2+.
не є мінімальними. Для множини (1) в правій частині першої FD присутня множина з двох
елементів. Для множини (2) видалення атрибуту Слу_імя з детермінанта другої FD не міняє
замикання множини FD. Для множини (3) видалення першої FD не приводить до зміни
замикання. Ці приклади показують, що для визначення мінімальності множини FD не завжди
потрібна явна побудова замикання даної множини.
Цікавим і важливим є той факт, що для будь-якої множини FD S існує (і навіть може бути
побудовано) еквівалентне йому мінімальна множина S-.
Оскільки для кожної множини FD існує еквівалентна мінімальна множина FD, у кожної
множини FD є хоч би одне мінімальне покриття, причому для його знаходження не
обов'язково знаходити замикання початкової множини.
Декомпозиція
Як вже наголошувалося, в наступній лекції ми обговорюватимемо підхід до проектування
реляційних баз даних на основі нормалізації, тобто декомпозиції (розбиття шляхом
проектування) відношення, що знаходиться в попередній нормальній формі, на два або
більш за відношення, що задовольняють вимогам наступної нормальної форми.
Теорема Хіта.
Доказ. Перш за все, доведемо, що в тілі результату природного з'єднання (позначимо цей
результат через r1) містяться всі кортежі тіла відношення r. Дійсно, хай кортеж {а, b, с} r.
Тоді за визначенням операції узяття проекції {а, b} (r PROJECT {A, B}) і {а,
с} (r PROJECT {A, С}). Отже, {а, b, с} r1. Тепер доведемо, що в тілі результату
природного з'єднання немає зайвих кортежів, тобто що якщо кортеж {а, b, с} r1, то {а, b,
с} r. Якщо {а, b, с} r1, то існують {а, b} (r PROJECT {A, B}) і {а, с} (r PROJECT {A, С}).
Остання умова може виконуватися в тому і лише у тому випадку, коли існує кортеж {а, b*,
с} r. Але оскільки виконується FD A B, то b = b* і, отже {а, b, с} = {а, b*, с}. Кінець
доказу.
Для подальшого викладу нам потрібно буде ввести ще одне визначення і зробити пару
зауважень.
Атрибут B мінімально залежить від атрибуту A, якщо виконується мінімальна зліва FD AB.
Далі, для ілюстрацій в наступній лекції нам стануть в нагоді діаграми FD, за допомогою яких
можна наочно представляти мінімальну множина FD. Наприклад, на мал. 6.6 приведена
діаграма мінімальної множини FD відношення Служащие_проєкти.
У лівій частці діаграми всі стрілки починаються з атрибуту Слу_ном, який є єдиним
можливим (і, отже, первинним) ключем відношення Служащие_проєкти. Звернете увагу на
відсутність стрілки від Слу_ном до Проєкт_рук. Звичайно, оскільки Слу_ном є можливим
ключем, повинна виконуватися і FD Слу_ном проєкт_рук. Але ця FD є транзитивною
(через Про_ном) і тому не входить в мінімальну множина FD. Відмітимо, що в процесі
нормалізації, до розгляду якого ми приступимо в наступній лекції, з діаграм
множини FD віддаляються стрілки, що починаються не від можливих ключів.
Подібні аномалії в даних лише частково дають відповідь на питання, чому логічна
структура реляційної БД може бути незадовільною. Деякі проблеми надмірності даних можна
вирішити, замінивши, наприклад, початкове відношення ПОСТАЧАННЯ на два нові
відношення - відношення ПОСТАЧАЛЬНИК (Постачальник, Адреса) і відношення
ПОСТАЧАННЯ (Постачальник, Товар, Кількість, Вартість). Проте в цілому залишається ряд
питань, на які теорія реляційних баз даних не дає задовільних відповідей: quot;Как знайти
хорошу заміну для поганої схеми відношень? Як визначити, чи є вибрана заміна вигідної? Як
створити схему, що забезпечує якнайкращу продуктивність?quot;
Наприклад, для того, щоб виконати запит, що використовує дані з двох таблиць, необхідно
побудувати з'єднання цих таблиць, яке є дорогою операцією з фізичною базою даних з погляду
числа виконуваних операцій введення/виводу.
Теорія функціональних залежностей дозволяє встановити певні вимоги до схем відношень
в реляційній базі даних. Ці вимоги формулюються в термінах властивостей відношень і
називаються нормальними формами схем відношень. Кожна нормальна форма відношень
пов'язана з певним класом ФЗ, які представлені в відношеннях. Зрозуміло, що одним з
очевидних способів усунення потенційної суперечності даних в відношеннях логічної моделі
реляційної бази даних є їх розбиття на два або більш за відношення, в кожному з яких
присутній тільки одна ФЗ.
Це можливо, оскільки теорія ФЗ стверджує, що існує мінімальне покриття множинаі ФЗ
бази даних, тобто мінімальний набір ФЗ, з яких можна вивести всі останні. Кожній ФЗ з
мінімального покриття можна відвести по самостійному відношенню. Проте, по-перше, для
заданої множинаі ФЗ може існувати декілька мінімальних покриттів (вибір серед можливих
альтернатив), і, по-друге, для практики поважно мати наочний спосіб побудови мінімального
покриття.
Процес усунення потенційної суперечності і надмірності даних в відношеннях реляційної
бази даних називається нормалізацією початкових схем відношень. Нормалізація відношень
полягає у виконанні декомпозиції або синтезу відношень, призначенні ключів відношень
відповідно до певних правил, що гарантують цілісність відношень бази даних. Вимога
мінімальності числа відношень, тобто побудови мінімального покриття ФЗ зазвичай є
опциональным. На мінімальному покритті, як правило, не може бути досягнута висока
продуктивність обробки запитів.
Чому нормалізація схем відношень важлива для проектування реляційних баз даних?
Численні випробування показали, що нормалізація схем відношень дає якнайкращий
результат при моделюванні наочної області з використанням реляційної моделі даних; при
цьому не вводиться великого числа обмежень, не спотворюються дані. Таким чином,
нормалізація відношень є методом видалення з відношення ФЗ, які приводять до аномалій
модифікації даних. Іншими словами, нормалізація відношень допомагає проектувати
реляційну базу даних, яка не містить надлишкових даних і гарантує їх цілісність.
Мову нормальних форм констатує наявність або відсутність певних ФЗ в відношеннях
реляційної бази даних і указує на рівень надмірності і надійності даних в нормалізованих
відношеннях. Методи нормалізації відношень грунтуються на застосуванні поняття ФЗ і
способів маніпулювання ними. При виконанні реляційних операцій над стосунками в базі
даних кожен тип ФЗ може породжувати певного типа аномалій, який порушуватиме цілісність
даних в базі даних. Нормальна форма (НФ) є обмеженням на схему бази даних, що вводиться
з метою усунення певних небажаних властивостей при виконанні реляційних операцій.
Нормальні форми
Вихідною точкою є представлення предметної області у вигляді одного або декількох
відношень, і на кожному кроці проектування проводиться деякий набір схем відношень, що
володіють кращими властивостями.
Процес проектування являє собою процес нормалізації схем відносин, причому кожна
наступна нормальна форма володіє кращим набором властивостей, ніж попередня.
СПІВРОБІТНИКИ-ВІДДІЛИ-ПРОЕКТИ
( СПІВР_НОМЕР, СОТР_ЗАРП, ОТД_НОМЕР, ПРО_НОМЕР, СПІВР_ЗАВДАН )
Первинний ключ: СПІВР_НОМЕР, ПРО_НОМЕР
Функціональні залежності:
СПІВР_НОМЕР-> СОТР_ЗАРП
СПІВР_НОМЕР-> ОТД_НОМЕР
ОТД_НОМЕР-> СОТР_ЗАРП
СПІВР_НОМЕР, ПРО_НОМЕР-> СПІВР_ЗАВДАН
Кожне з цих двох відношень знаходиться в 2NF, і в них усунені зазначені вище аномалії
(легко перевірити, що всі зазначені операції виконуються без проблем).
Під проектуванням без втрат розуміється такий спосіб декомпозиції відношення, при якому
початкове відношення повністю і без надмірності відновлюється шляхом природного
з'єднання отриманих відношень.
Отож легко показати, що при вставках і видаленнях кортежів можуть виникнути проблеми.
Їх можна усунути шляхом декомпозиції початкового відношення в три нових відносини:
СПІВРОБІТНИКИ-ВІДДІЛИ ( СПІВР_НОМЕР, ОТД_НОМЕР )
П'ята нормальна форма-це остання нормальна форма, яку можна отримати шляхом
декомпозиції. Її умови досить нетривіальні, і на практиці 5NF не використовується.
Зауважимо, що залежність з'єднання є узагальненням як багатозначної залежності, так і
функціональної залежності.
Отже, кожна нормальна форма обмежує певного типа ФЗ і усуває аномалії обробки даних.
Нормальні форми характеризуються наступними властивостями:
1НФ - всі атрибути відношення прості;
2НФ - відношення знаходиться в 1НФ і не містить часткових ФЗ;
3НФ - відношення знаходиться в 2НФ і не містить транзитивних ФЗ від ключа;
НФБК - відношення знаходиться в 3НФ і не містить ФЗ ключів від неключових атрибутів;
4НФ, застосовується за наявності більш ніж одній багатозначною ФЗ - відношення
знаходиться в НФБК або 3НФ і не містить незалежних багатозначних ФЗ;
5НФ - відношення знаходиться в 4НФ і не містить ФЗ по з'єднанню.
Кожен екземпляр сутності повинен відрізнити від будь-якого іншого екземпляра тієї ж
сутності (це вимога в деякому роді аналогічно вимозі відсутності кортежів - дублікатів в
реляційних таблицях ) .
Як і сутність , зв'язок - це типове поняття , всі примірники обох пар пов'язують сутностей
підкоряються правилам зв'язування .
Потужність визначає тип зв’язку між сутностями. Так на рисунку схеми є прикладами
зв’язків:
(b) один-до-багатьох 1:N (one-to-many),
(с) один-до-одного 1:1 (one-to-one),
(d) M:N (many-to-many)
Ці та інші більш складні елементи моделі даних " Сутність-Зв'язок " роблять її істотно
потужнішою , але одночасно дещо ускладнюють її використання . Зазвичай , при реальному
використанні ER -діаграм для проектування баз даних необхідно ознайомитися з усіма
можливостями.
Як це читати ?
Від супертипа : літальний апарат , який може бути АЕРОПЛАН , ВЕРТОЛІТ , ЦЕПЕЛІН
або ІНШИЙ .
Від підтипу: ВЕРТОЛІТ , який відноситься до типу літальних апаратів.
Від підтипу , який є одночасно супертип : АЕРОПЛАН , який відноситься до
типу ЛІТАЛЬНИХ АПАРАТІВ і повинен бути ПЛАНЕР або МОТОРНИЙ ЛІТАК.
Крок 1 .
Кожна проста сутність перетворюється в таблицю .
Проста сутність - сутність , яка не є підтипом і не має підтипів .
Ім'я суті стає ім'ям таблиці.
Крок 2 .
Кожен атрибут стає можливим стовпцем з тим же ім'ям, може вибиратися більш точний
формат .
Стовпці , що відповідають необов'язковим атрибутам , можуть містити невизначені
значення; стовпці, що відповідають обов'язковим атрибутами , - не можуть.
Крок 3 .
Компоненти унікального ідентифікатора сутності перетворюються на первинний ключ
таблиці.
Якщо є кілька можливих унікальних ідентифікаторів , вибирається найбільш
використовуваний .
Якщо до складу унікального ідентифікатора входять зв'язку , до числа стовпців первинного
ключа додається копія унікального ідентифікатора сутності , що знаходиться на другому кінці
зв'язку (цей процес може тривати рекурсивно ) . Для іменування цих стовпців
використовуються імена решти зв'язків та / або імена сутностей.
Крок 4 .
Зв'язки багато-до-одного (і один- до-одного ) стають зовнішніми ключами. Тобто робиться
копія унікального ідентифікатора з кінця зв'язку "один" , і відповідні стовпці складають
зовнішній ключ.
Необов'язкові зв'язки відповідають стовпцях, що допускають невизначені значення ;
обов'язкові зв'язку - стовпцях, що не допускає невизначені значення.
Крок 5 .
Індекси створюються для первинного ключа (унікальний індекс) , зовнішніх ключів і тих
атрибутів , на яких передбачається в основному базувати запити.
Крок 6 .
Якщо в концептуальній схемі були присутні підтипи , то можливі два способи :
- всі підтипи в одній таблиці ( а )
- для кожного підтипу - окрема таблиця (б)
При застосуванні способу ( а ) таблиця створюється для найбільш загального супертипу , а
для підтипів можуть створюватися представлення. У таблицю додається принаймні один
стовпець, що містить код ТИПУ, він стає частиною первинного ключа.
При використанні методу (б) для кожного підтипу першого рівня ( для більш нижніх -
представлень) супертип відтворюється за допомогою представлення UNION ( з усіх таблиць
підтипів вибираються загальні стовпці - стовпці супертипу ) .
Все в одній таблиці Таблиця - на підтип
Переваги
Всі зберігається разом Більш ясні правила підтипів
Легкий доступ до супертипа і підтипів Програми працюють тільки з
Потрібно менше таблиць потрібними таблицями
Недоліки
Занадто загальне рішення
Занадто багато таблиць
Потрібна додаткова логіка роботи з різними
Стовпці в представленням UNION
наборами стовпців і різними обмеженнями
Потенційна втрата продуктивності при
Потенційне вузьке місце (у зв'язку з блокуваннями)
роботі через UNION
Стовпці підтипів повинні бути необов'язковими
Над супертипом неможливі
У деяких СУБД для зберігання невизначених значень
модифікації
потрібна додаткова пам'ять
Крок 7 .
Є два способи роботи за наявності виключачих зв'язків:
- загальний домен ( а )
- явні зовнішні ключі (б)
Якщо зовнішні ключі всі в одному домені , тобто мають загальний формат (спосіб ( а )) , то
створюються два стовпці : ідентифікатор зв'язку та ідентифікатор сутності. Стовпець
ідентифікатора зв'язку використовується для розрізнення зв'язків , що покриваються дугою
виключення . Стовпець ідентифікатора суті використовується для зберігання значень
унікального ідентифікатора суті на далекому кінці відповідної зв'язку .
Якщо результуючі зовнішні ключі не відносяться до одного домену , то для кожного зв'язку,
що покривається дугою виключення , створюються явні стовпці зовнішніх ключів; всі ці
стовпці можуть містити невизначені значення .
Варіант 1 (поганий)
ER-діаграми
Широке розповсюдження реляційних СУБД і їх використання в найрізноманітніших
застосуваннях показує, що реляційна модель даних достатня для моделювання
різноманітних наочних областей. Проте проектування реляційної бази даних в термінах
стосунків на основі того, що короткий розглянуті нами в двох попередніх лекціях механізму
нормалізації часто є дуже складним і незручним для проектувальника процесом.
Тут слід зробити два зауваження, що стосуються, головним чином, термінології. Обидва
терміни relation і relationship можуть бути перекладені на російську мову як відношення.
Тому в російськомовній літературі ER-модель інколи називають моделлю суть-відношення,
а інколи і реляційною семантичною моделлю. Напевно, в цьому немає нічого страшного,
якщо говорити про ER-модели у відриві від тематики проектування реляційних баз даних.
Зв'язок представляється у вигляді ненапрямленої лінії, що сполучає дві суті або ведучу від
суті до неї ж самої. При цьому в місці «стиковки» зв'язку з суттю використовуються:
* триточковий вхід в прямокутник суті, якщо для цієї суті в зв'язку можуть (або повинні)
використовуватися багато (many) екземплярів суті;
* одноточечний вхід, якщо в зв'язку може (або повинен) брати участь тільки один
екземпляр суті.
Зв'язок між суттю КВИТОК і ПАСАЖИР, показана на мал. 9.2, зв'язує квитки і пасажирів.
Кінець зв'язку з ім'ям «для» дозволяє пов'язувати з одним пасажиром більш як один квиток,
причому кожен квиток має бути пов'язаний з яким-небудь пасажиром. Кінець зв'язку з ім'ям
«має» показує, що кожен квиток може належати тільки одному пасажирові, причому
пасажир не зобов'язаний мати хоч би одного квитка.
Атрибутом суті є будь-яка деталь, яка служить для уточнення, ідентифікації, класифікації,
числової характеристики або вираження стану суті. Імена атрибутів заносяться в
прямокутник, що змальовує суть, під ім'ям суті і змальовуються малими буквами, можливо,
з прикладами. Приклад типа суті ЧОЛОВІК з вказаними атрибутами показаний на мал. 9.4.
З технічної точки зору атрибути типа суті в ER-модели схожі на атрибути відношення в
реляційній моделі даних. І у тому, і в іншому випадках введення іменованих атрибутів
вводить деяку типову структуру даних, ім'я якої збігається з ім'ям типа суті в разі ER-модели
або з ім'ям змінної відношення в разі реляційної моделі.
Цій типовій структурі повинні слідувати всі екземпляри типа суті або всі кортежі відношення.
Але є і важлива відмінність. Нагадаємо, що в реляційній моделі даних атрибут визначається
як впорядкована пара <имя_атрибута, имя_домена> (або <имя_атрибута,
имя_базового_типа_данных>, якщо поняття домена не підтримується). Заголовок
відношення, визначуваний як безліч таких пар, є повним аналогом структурного типа даних
в мовах програмування.
Але при проектуванні бази даних мало того, щоб проектувальник переконався в
правильному виборі типів суті, що гарантує відмінність екземплярів кожного типа суті.
Необхідно повідомити систему автоматизації проектування БД, яким чином розрізнятимуться
ці екземпляри, тобто повідомити, як конструюються унікальні ідентифікатори екземплярів
кожного типа суті. У ER-модели у екземпляра типа суті не може бути імені, що призначається
користувачем, або зовнішнього унікального ідентифікатора, що призначається системою.
Екземпляр типа суті може ідентифікуватися тільки своїми індивідуальними
характеристиками, а вони представляються значеннями атрибутів і екземплярами типів
зв'язку, що зв'язують даний екземпляр типа суті з екземплярами інших типів суті або цього
ж типа суті. Тому унікальним ідентифікатором суті може бути атрибут, комбінація атрибутів,
зв'язок, комбінація зв'язків або комбінація зв'язків і атрибутів, що унікально відрізняє будь-
який екземпляр суті від інших екземплярів суті того ж типа.
Наведемо декілька прикладів. На мал. 9.5 показаний тип суті КНИГА, придатний для
використання в базі даних книжкового складу. При виданні будь-якої книги в будь-якому
видавництві (окрім піратських, якими ми для простоти нехтуватимемо) їй привласнюється
унікальний номер - ISBN. Зрозуміло, що значення атрибуту isbn унікально
ідентифікуватиме партію книг на складі. Крім того, звичайно, як унікальний ідентифікатор
годиться і комбінація атрибутів <автор, назва, номер видання, видавництво, рік видання>.
Мал. 9.5. Тип суті, екземпляри якого ідентифікуються атрибутами
На мал. 9.6 діаграма включає два зв'язаних типи суті. У кожної дорослої людини є один і
лише один паспорт (ми знову не беремо в розрахунок особливий випадок, коли у однієї
людини є декілька паспортів), і кожен паспорт може належати тільки одній дорослій людині
(деякі вже готові паспорти можуть бути ще нікому не видані). Тоді зв'язок людини з його
паспортом (кінець зв'язку МАЄ) унікально ідентифікує дорослу людину, т. е., грубо кажучи,
паспорт визначає дорослу людину. Оскільки можуть існувати паспорти, ще не видані якій-
небудь людині, цей зв'язок не є унікальним ідентифікатором суті ПАСПОРТ.
На мал. 9.7 діаграма включає трьох зв'язаних типів суті. Професори володіють знаннями в
декількох учбових дисциплінах. Викладання кожної дисципліни доступне декільком
професорам. Іншими словами, між суттю ПРОФЕСОР і ДИСЦИПЛІНА визначений зв'язок
«багато до багатьом». Кожен професор може готувати курси по будь-якій доступній йому
дисципліні. Кожній дисципліні може бути присвячене декілька учбових курсів. Але кожен
професор може готувати тільки один курс по будь-якій доступній йому дисципліні, і кожен
курс може бути присвячений тільки одній дисципліні. Тим самим, кожен екземпляр типа
суті КУРС унікально ідентифікується екземпляром суті ПРОФЕСОР і екземпляром
суті ДИСЦИПЛІНА, тобто парою зв'язків з іменами кінців ГОТУЄТЬСЯ і ПРИСВЯЧЕНИЙ на
стороні суті КУРС. Відмітимо, що суть ПРОФЕСОР і ДИСЦИПЛІНА зв'язками не
ідентифікуються.
На мал. 9.9 (a) показана діаграма, в якій типа суті АЕРОПОРТ не задовольняє вимозі першої
нормальної форми. Тут для нас неістотні атрибути суті АВІАРЕМОНТНЕ ПІДПРИЄМСТВО, але
суть АЕРОДРОМ окрім атрибутів, що відображають власні характеристики аеродромів
(довжина злітно-посадочної смуги, число ангарів і так далі) містить атрибут, множинне
значення якого характеризує літаки, приписані до цього аеродрому. Очевидно, що літаки
потребують ремонту, тобто повинні обслуговуватися деяким авіаремонтним підприємством.
Але оскільки літаки є часткою суті АЕРОДРОМ, єдиним способом фіксації цього факту на
діаграмі є проведення зв'язку «багато до багатьом» між типами суті АЕРОДРОМ і
АВІАРЕМОНТНЕ ПІДПРИЄМСТВО. Таким чином виражається те міркування, що для ремонту
різних літаків, приписаних до одного аеродрому, можуть використовуватися різні
транспортні підприємства, і кожне транспортне підприємство може обслуговувати декілька
аеродромів.
Чим погана ця ситуація? Перш за все, тим, що ховається той факт, що авіаремонтне
підприємство ремонтує літаки, а не аеродроми. Наш же зв'язок насправді означає, що будь-
який аеродром з групи аеродромів обслуговується будь-яким авіаремонтним підприємством
з групи таких підприємств. Проблема полягає саме в тому, що значенням атрибуту «літаки»
є безліч екземплярів типа суті ЛІТАК, і цей тип суті сам володіє атрибутами і зв'язками.
Ситуацію виправляє ER-диаграмма, показана на мал. 9.9 (b). Тут ми виділили типа
суті ЛІТАК. Зв'язок між суттю АЕРОДРОМ і ЛІТАК показує, що до одного аеродрому
приписується декілька літаків. Зв'язок між суттю ЛІТАК і АВІАРЕМОНТНЕ ПІДПРИЄМСТВО
означає, що кожен літак з групи літаків (групу літаків можуть складати, наприклад, всі
літаки одного типа) обслуговується будь-яким транспортним підприємством з деякої групи
таких підприємств. ER-диаграмма на мал. 9.9 (b) знаходиться в першій нормальній формі і,
як ми бачимо, краще відображує реальну ситуацію.
Друга нормальна форма ER-диаграммы
У другій нормальній формі усуваються атрибути, залежні тільки від частки унікального
ідентифікатора. Ця частка унікального ідентифікатора визначає окрему суть.
На мал. 9.10 (a) показана діаграма, на якій тип суті ЕЛЕМЕНТ РОЗКЛАДУ не задовольняє
вимогам другої нормальної форми. На цій діаграмі у суті ЕЛЕМЕНТ РОЗКЛАДУ є наступні
властивості. Елементи розкладу призначені для збереження даних про рейси літаків, що
вилітають протягом дня. Деякими важливими характеристиками рейса є номер рейса,
аеропорт вильоту, аеропорт призначення, дата і час вильоту, бортовий номер літака, тип
літака. Якщо говорити про російські авіаційні компанії, то (1) у кожного рейса є заздалегідь
приписаний йому номер (унікальний серед всіх інших наявних номерів рейсів), (2) не всі
рейси здійснюються щодня, тому характеристикою конкретного рейса є дата і час його
здійснення, (3) бортовий номер літака визначається парою <номер рейса, дата-час
вильоту>. Є зв'язок «багато до одного» між суттю ЕЛЕМЕНТ РОЗКЛАДУ і МІСТО. Екземпляри
типа суті МІСТО характеризують місто, в яке прибуває даний рейс.
Мал. 9.10. Приклад приведення ER-диаграммы до другої нормальної форми
Унікальним ідентифікатором типа суті ЕЛЕМЕНТ РОЗКЛАДУ є пара атрибутів <номер рейса,
дата-час вильоту>. Якщо повернутися до термінів функціональних залежностей, то між
атрибутами цієї суті є наступні FD:
* { номер рейса, дата-час вильоту}бортовий номер літака;
* номер рейса аеропорт вильоту;
* номер рейса аеропорт призначення;
* бортовий номер літака тип літака.
Крім того, очевидно, що кожен екземпляр зв'язку з суттю МІСТО також визначається
значенням атрибуту номер рейса. У наявності порушення вимоги другої нормальної форми.
Ми отримуємо не лише надлишкове зберігання значень атрибутів аеропорт вильоту і
аеропорт призначення в кожному екземплярі типа суті ЕЛЕМЕНТ РОЗКЛАДУ з одним і тим
же значенням номера рейса. Спотворюється і затьмарюється сенс зв'язку з суттю МІСТО.
Можна подумати, що в різні дні один і той же рейс прибуває в різні міста.
На мал. 9.10 (b) показаний нормалізований варіант діаграми, в якому вся суть знаходиться
в другій нормальній формі. Тепер є три типи суті: РЕЙС з атрибутами номер рейса, аеропорт
вильоту, аеропорт призначення, ЕЛЕМЕНТ РОЗКЛАДУ з атрибутами дата-час вильоту,
бортовий номер літака, тип літака і МІСТО. Унікальним ідентифікатором суті РЕЙС є
атрибут номер рейса, унікальний ідентифікатор ЕЛЕМЕНТ РОЗКЛАДУ складається з
атрибуту дата вильоту і кінця зв'язку КОЛИ, НА ЧОМУ. Ми бачимо, що ні в одному типові
суті більше немає атрибутів, визначуваних часткою унікального ідентифікатора. Властивості
другої нормальної форми задовольняються, і ми маємо якіснішу діаграму.
Третя нормальна форма ER-диаграммы
Поглянемо ще раз на типа суті ЕЛЕМЕНТ РОЗКЛАДУ на мал. 9.10 (b). Звичайно, щодня
кожен рейс виконується тільки одним літаком, тому бортовий номер літака повністю
залежить від унікального ідентифікатора. Але бортовий номер є унікальною
характеристикою кожного літака, і від цієї характеристики залежить решта всіх
характеристик, зокрема тип літака. Іншими словами, між унікальним ідентифікатором і
іншими атрибутами типа суті ЕЛЕМЕНТ РОЗКЛАДУ є наступні функціональні залежності:
Як же слід розуміти діаграму, представлену на мал. 9.12? Якщо починати від супертипа, то
діаграма змальовує ЛІТАЛЬНИЙ АПАРАТ, який має бути АЕРОПЛАНОМ, ВЕРТОЛЬОТОМ,
ПТІЦЕЛЕТОМ або ІНШИМ ЛІТАЛЬНИМ АПАРАТОМ. Якщо починати від підтипу (наприклад,
суть ВЕРТОЛІТ), то це ВЕРТОЛІТ, який відноситься до типу ЛІТАЛЬНОГО АПАРАТУ. Якщо
починати від підтипу, який є одночасно супертипом, то це АЕРОПЛАН, який відноситься до
типу ЛІТАЛЬНОГО АПАРАТУ і має бути ПЛАНЕРОМ або МОТОРНИМ ЛІТАКОМ.
В даному випадку для кожного екземпляра типа суті ЛІТАК повинен існувати екземпляр
одного з вказаних зв'язків. Для екземплярів типу суті ЛІТАК, відповідних справним літакам,
повинен існувати екземпляр зв'язку «один до одного» з екземпляром типу суті ПІЛОТ, а
екземпляри, відповідні несправним літакам, повинні брати участь в екземплярі типу зв'язку
«багато до одного» з екземпляром типу суті АВІАРЕМОНТНЕ ПІДПРИЄМСТВО.
Відмітимо, що для того, щоб описана схема реалізації механізму зв'язків, що взаємно
виключають, на основі механізму спадкоємства дійсно могла працювати, в засобах
маніпулювання даними ER-модели має бути передбачена можливість динамічної зміни типа
суті у екземпляра. Конкретно для нашого випадку потрібна можливість зміни типа
екземпляра суті СПРАВНИЙ ЛІТАК на типа суті НЕСПРАВНИЙ ЛІТАК, і навпаки (справний
літак може ламатися, несправний літак - приводитися в робочий стан). Звичайно, при такій
зміні типа повинен змінюватися і екземпляр зв'язку. Відмітимо, що в даному випадку ми
маємо справу з обмеженою динамічною зміною типа екземпляра, оскільки і справні, і
несправні літаки є екземплярами супертипа ЛІТАК.
Отримання реляційної схеми з ER-диаграммы
Опишемо типову багатокрокову процедуру перетворення ER-диаграммы в реляційну
(точніше, в SQL-ориентированную) схему бази даних.
Базові прийоми
Кожен простий тип суті перетворюється на таблицю. (Простим типом суті називається тип
суті, що не є підтипом і що не має підтипів.) Ім'я суті стає ім'ям таблиці. Екземплярам типу
суті відповідають рядки відповідної таблиці.
Кожен атрибут стає стовпцем таблиці з тим же ім'ям; може вибиратися точніший формат
представлення даних. Стовпці, відповідні необов'язковим атрибутам, можуть містити
невизначені значення; стовпці, відповідні обов'язковим атрибутам, - не можуть.
Компоненти унікального ідентифікатора суті перетворюються на первинний ключ таблиці.
Якщо є декілька можливих унікальних ідентифікаторів, для первинного ключа вибирається
найбільш характерний. Якщо до складу унікального ідентифікатора входять зв'язки, до
стовпців первинного ключа додається копія унікального ідентифікатора суті, що
знаходиться на іншому кінці зв'язку (цей процес може продовжуватися рекурсивно, і в
загальному випадку може привести до зациклення). Для іменування цих стовпців
використовуються імена кінців зв'язків і/або імена парних типів суті.
Для підтримки зв'язку «багато до багатьом» між типами суті A і B створюється додаткова
таблиця AB з двома стовпцями, один з яких містить унікальні ідентифікатори екземплярів
суті A, а інший - унікальні ідентифікатори екземплярів суті B. Позначимо
через AB(с) унікальний ідентифікатор екземпляра з деякого типа суті C. Тоді, якщо в
екземплярі зв'язку «багато до багатьом» беруть участь екземпляри a1, a2 ..., an типа
суті A і екземпляри b1, b2 ..., bm типа суті B, то в таблиці AB мають бути присутніми всі
рядки вигляду < AB (ai), AB(bj)> для i = 1, 2 ..., n, j = 1, 2 ..., m. Зрозуміло, що,
використовуючи таблиці A, B і AB, за допомогою стандартних реляційних операцій можна
знайти всі пари екземплярів типів суті, що беруть участь в даному зв'язку.
При застосуванні способу (a) таблиця створюється для максимального супертипа (типа суті,
що не є підтипом), а для підтипів можуть створюватися представлення(проекції). Таблиця
містить стовпці, відповідні кожному атрибуту (і зв'язкам) кожного підтипу. У таблицю
додається, принаймні, один стовпець, що містить код ТИПу; він стає часткою первинного
ключа. Для кожного рядка таблиці значення цього стовпця визначає тип суті, екземпляру
якого відповідає рядок. Стовпці цього рядка, які відповідають атрибутам і зв'язкам, відсутнім
в даному типові суті, повинні містити невизначені значення.
При використанні методу (b) для кожного підтипу першого рівня (для глибших рівнів
застосовується метод (a)) супертип відтворюється за допомогою представлення UNION (зі
всіх таблиць підтипів вибираються загальні стовпці - стовпці супертипа).
У кожного способу є свої переваги та недоліки. До переваг першого способу (одна таблиця
для супертипа і всіх його підтипів) можна віднести наступне:
* відповідність логіці супертипів і підтипів; оскільки будь-який екземпляр будь-якого
підтипу є екземпляром супертипу, логічно зберігати разом всі рядки, відповідні екземплярам
супертипа;
* забезпечення простого доступу до екземплярів супертипа і не дуже складний доступ
до екземплярів підтипів;
* можливість обійтися невеликим числом таблиць.
Перевага підходу (a) полягає в тому, що в таблиці, відповідній суті, з'являється всього два
додаткові стовпці. Очевидним недоліком є ускладнення виконання операції з'єднання: щоб
скористатися для з'єднання одного з альтернативних зв'язків, потрібно спочатку провести
обмеження таблиці відповідно до потрібного значення стовпця, що містить ідентифікатори
зв'язків.
При використанні підходу (b) з'єднання є явними (і природними). Недолік полягає в тому,
що потрібно мати стільки стовпців, скільки є альтернативних зв'язків. Крім того, в кожному
з таких стовпців міститиметься багато невизначених значень, зберігання яких потенційно
може привести до серйозних накладних витрат зовнішньої пам'яті.
Мал. 9.14. Можливі модифікації ER-діаграм, що дозволяють уникнути зв'язків, що взаємно
виключають
Модифікація, показана на мал. 9.14 (b), заснована на тому спостереженні, що якщо зв'язки
є альтернативними, то вони розділяють безліч екземплярів суті A на два або більш
непересічних підмножини, які можуть лежати в основі визначення підтипів A1 і A2. Це
хороший варіант, якщо такі підтипи можуть стати в нагоді ще для чого-небудь. Наприклад,
в разі взаємного зв'язку, що виключає, представленого на мал. 9.12, у справних і
несправних літаків можуть имется неспівпадаюча безліч атрибутів (скажімо, у типа
суті СПРАВНІ ЛІТАКИ може бути атрибут дата завершення гарантійного терміну, а у типа
суті НЕСПРАВНІ ЛІТАКИ - атрибут тип несправності). З іншого боку, як наголошувалося в
попередньому розділі, для використання цього підходу потрібна можливість динамічної
зміни типа існуючого екземпляра.
Модифікація, показана на мал. 9.14 (с), заснована на тому спостереженні, що якщо типи
суті B і C беруть участь в альтернативному зв'язку, то, видно, у цієї суті є щось загальне.
Можливо, їх було б правильніше визначати як підтипи деякого загального типу суті.
Відмітимо, що приклад з мал. 9.12 явно демонструє, що далеко не завжди типи суті, що
беруть участь в альтернативному зв'язку, володіє загальними рисами.
Востаннє редаговано: Четвер, 11 лютого 2016, 13:31. Версія: 0. Опубліковано: Понеділок, 22
жовтня 2012, 18:00.
На самому нижньому рівні знаходяться найменші об'єкти, з якими працює реляційна база
даних, - стовпці (колонки) і рядки. Вони, у свою чергу, групуються в таблиці і
представлення.
Таблиці і представлення, які представляють фізичне віддзеркалення логічної структури бази
даних, збираються в схему. Декілька схем збираються в каталоги, які потім можуть бути
згруповані в кластери. Слід зазначити, що жодна з груп об'єктів стандарту SQL-92 не
пов'язана із структурами фізичного зберігання інформації в пам'яті комп'ютерів.
Окрім вказаних на рисунку об'єктів, в реляційній базі даних можуть бути створені індекси,
тригери, події, команди, процедури і ряд інших. Тепер перейдемо до визначення об'єктів
реляційної бази даних.
Кластери, каталоги і схеми не є обов'язковими елементами стандарту а, отже, і програмного
середовища реляційних баз даних.
Під кластером розуміється група каталогів, до яких можна звертатися через одне з'єднання
з сервером бази даних (програмна компонента СУБД).
На практиці процедура створення каталогу визначається реалізацією СУБД на конкретній
операційній платформі. Під каталогом розуміється група схем. На практиці каталог часто
асоціюється з фізичною базою даних як набором фізичних файлів операційної системи, які
ідентифікуються її ім'ям.
Для проектувальника бази даних схема - це загальне логічне представлення відношень
закінченої бази даних. З погляду SQL, схема - це контейнер для таблиць, представлень і
інших структурних елементів реляційної бази даних. Принцип розміщення елементів бази
даних в кожній схемі повністю визначається проектувальником бази даних.
Для створення таблиць і уявлень наявність схеми не обов'язкова. Якщо у вас планується
інсталяція тільки однієї логічної бази даних, то ясно, що можна обійтися і без схеми. Але
якщо планується, що одна і та ж СУБД використовуватиметься для підтримки декількох баз
даних, то належна організація об'єктів баз даних в схеми може значно полегшити супровід
цих баз даних. На практиці схема часто асоціюється з об'єктами певного користувача
фізичної бази даних.
Далі об'єкти реляційної бази даних вводитимуться в контексті реляційної СУБД Oracle 9i.
Такий підхід прийнятий тому, що проектування фізичної моделі реляційної бази даних
виконується для конкретної середи її реалізації.
У Oracle 9i термін схема (Schema) використовується для опису всіх об'єктів бази даних, які
створені деяким користувачем. Для кожного нового користувача автоматично створюється
нова схема.
До основних об'єктів реляційних баз даних належать таблиця, представлення і користувач.
Таблиця (Table) є базовою структурою реляційної бази даних. Вона є одиницею зберігання
даних - відношенням. Таблиця ідентифікується в базі даних своїм унікальним ім'ям, яке
включає ідентифікацію користувача. Таблиця може бути порожньою або складатися з
набору рядків.
Представлення (View) - це поіменована динамічно підтримувана СУБД вибірка з однієї або
декількох таблиць бази даних. Оператор вибірки обмежує видимі користувачем дані.
Зазвичай СУБД гарантує актуальність уявлення - його формування проводиться кожного
разу, коли уявлення використовується. Інколи уявлення називають віртуальними
таблицями.
Користувач (User) - це об'єкт, що володіє можливістю створювати або використовувати інші
об'єкти бази даних і запрошувати виконання функцій СУБД, таких як організація сеансу
роботи, зміна стан бази даних і так далі
Для спрощення ідентифікації і іменування об'єктів в базі даних підтримується такі об'єкти,
як синонім, послідовність і визначені користувачем типи даних.
Синонім (Synonym) - це альтернативне ім'я об'єкту (псевдонім) реляційної бази даних, яке
дозволяє мати доступ до даного об'єкту. Синонім може бути загальним і приватним.
Загальний синонім дозволяє всім користувачам бази даних звертатися до відповідного
об'єкту по його псевдоніму. Синонім дозволяє приховати від кінцевих користувачів повну
кваліфікацію об'єкту в базі даних.
Індекс (Index) - це об'єкт бази даних, що створюється для підвищення продуктивності
вибірки даних і контролю унікальності первинного ключа (якщо він заданий для таблиці).
Повністю індексні таблиці (index-organized tables) виконують роль таблиці і індексу
одночасно.
Табличний простір або область (Tablespace) - це іменована частка бази даних,
використовувана для розподілу пам'яті для таблиць і індексів. У Oracle 9i - це логічне ім'я
фізичних файлів операційної системи. Всі об'єкти бази даних, в яких зберігаються дані,
відповідають деяким табличним просторам. Більшість об'єктів бази даних, в яких дані не
зберігаються, знаходяться в словнику даних, розташованому в табличному просторі
SYSTEM.
Кластер (Cluster) - це об'єкт, задаючий спосіб сумісного зберігання даних в декількох або
одній таблиці. Одним з критеріїв використання кластера є наявність загальних ключових
полів в декількох таблицях, які використовуються в одній і тій же команді SQL. Зазвичай
кластеризовані стовпці або таблиці зберігаються в базі даних у вигляді таблиць хешування
(тобто спеціальним чином).
Секція (Partition) - це об'єкт бази даних, який дозволяє представити об'єкт з даними у
вигляді сукупності підоб'єктів, віднесених до різних табличних просторів. Таким чином,
секціонування дозволяє розподіляти дуже великі таблиці на декількох жорстких дисках.
Даними об'єктами реляційної бази даних є програми, тобто виконуваний код. Цього код
зазвичай називають серверним кодом (server-side code), оскільки він виконується
комп'ютером, на якому встановлено ядро реляційної СУБД. Планування і розробка такого
коду є одним із завдань проектувальника реляційної бази даних.
Команда CREATE DATABASE створює базу даних з вказаним ім'ям. Для використання
команди необхідно мати привілей CREATE для бази даних. Якщо база даних з таким ім'ям
існує, генерується помилка.
спецификация_create:
[DEFAULT] CHARACTER SET имя_набора_символов
[DEFAULT] COLLATE имя_порядка_сопоставления
Бази даних в MYSQL реалізовані у вигляді каталогів, які містять файли, відповідні таблицям
бази даних. Оскільки спочатку в базі немає ніяких таблиць, оператор CREATE DATABASE
тільки створює підкаталог в каталозі даних MYSQL.
Бази даних зберігають дані в таблицях. Чим же є ці таблиці? Найпростіше таблиці можна
уявляти собі, як що складаються з рядків і стовпців. Кожен стовпець визначає дані певного
типа. Рядки містять окремі записи.
Розгледимо таблицю 3.1, в якій приведені персональні дані деяких людей:
Таблиця 3.1. Персональні дані
Ім'я Вік Країна e-mail
Михайло Петров 28 Росія misha@yandex.ru
Джон Доусон 32 Австралія j.dow@australia.com
Моріс Дрюон 48 Франція md@france.fr
Снежана 19 Болгарія sneg@bulgaria.com
Всякий раз при роботі з клієнтом mysql необхідно визначати, яка база даних
використовуватиметься.
Визначити поточну базу даних можна декількома способами:
- визначення імені бази даних при запуску
mysql employees (у Windows)
mysql employees -u manish -p (у Linux)
Створення таблиці
Команда SQL для створення таблиці має наступний вигляд:
Примітка: у MYSQL команди і імена стовпців не розрізняють регістр символів, проте імена
таблиць і баз даних можуть залежати від регістра у зв'язку з використовуваною платформою
(як в Linux).
За ключовими словами CREATE TABLE слідує ім'я створюваної таблиці employee_data. Кожен
рядок усередині дужок представляє один стовпець. Ці стовпці зберігають для кожного
співробітника ідентифікаційний номер (emp_id), прізвище (name) вік (вік), стаж роботи в
компанії (yos), і адресу електронна пошта (електронна пошта).
За ім'ям кожного стовпця слідує тип стовпця. Типи стовпців визначають типа даних, які
міститиме стовпець. Перший стовпець (emp_id) містить ідентифікаційний номер (id)
співробітника.
- int: визначає типа стовпця як ціле число.
- unsigned: визначає, що число буде без знаку (позитивне ціле).
- not null: визначає, що значення не може бути порожній покажчик (порожнім); тобто
кожен рядок в цьому стовпці повинен мати значення.
- auto_increment: коли MYSQL зустрічається компанія стовпцем з
атрибутом auto_increment, то генерується нове значення, яке на одиницю більш ніж
найбільше значення в стовпці. Тому ми не повинні задавати для цього стовпця
значення, MYSQL генерує їх самостійно. З цього також виходить, що кожне значення в
цьому стовпці буде унікальним.
primary key: допомагає при індексуванні стовпця, що прискорює пошук значень. Кожне
значення має бути унікальне. Ключовий стовпець необхідний для того, щоб унеможливити
збігу даних. Наприклад, два співробітники можуть мати одне і те ж ім'я, і тоді встане
проблема - як розрізняти цих співробітників, якщо не задати їм унікальні ідентифікаційні
номери. Якщо є стовпець з унікальними значеннями, то можна легко розрізнити два записи.
Краще всього доручити привласнення унікальних значень самій системі MYSQL.
Щоб задати ім'я таблиці з пропусками, необхідно взяти його в зворотні лапки, наприклад
'Courses list'. Те ж саме потрібно буде робити у всіх посиланнях на таблицю, оскільки
пропуски використовуються для розділення ідентифікаторів.
Дозволяється створювати таблиці без стовпців, проте в більшості випадків специфікація хоч
би одного стовпця все ж присутня. Специфікації стовпців і індексів приводяться в круглих
дужках і розділяються комами. Формат специфікації наступний:
ім'я тип
[NOT NULL | NULL]
[DEFAULT значення]
[AUTO_INCREMENT]
[KEY]
[посилання]
Видалення таблиці
Для того, щоб видалити таблицю, переконаємося спершу що вона існує. Це можна
перевірити за допомогою команди SHOW TABLES
Частка оператора з умовами є необов'язковою. По суті, потрібно знати імена стовпців і ім'я
таблиці, з якої витягуються дані.
Оператори порівняння = і !=
SELECT name from employee_data where country="Україна";
Слово HAVING
Щоб вивести середній вік працівників для кожної із країн, можна скористатися запитом
GROUP BY, наприклад:
Тепер, якщо нам потрібний перелік тільки тих країн, для яких середній вік працівників
складає більше 30, то можемо записати
Примітка: Якщо ніякі умови не будуть задані, то віддаляються всі дані в таблиці.
В якості прикладу можна спробувати змінити назву посади "Розробник Web" "програміст
Web".
Логічні операції
У лекції розглядуються логічні оператори і способи їх застосування в MySql. Також
розглядуються способи впорядковування даних, способи обмеження витягуваних даних і
команди оновлення записів.
Ось складніший приклад ... список імен і віку співробітників, прізвища яких починаються з
До або Л, і які молодше 30 років.
Оператори IN і BETWEEN
Щоб знайти співробітників, які є розробниками Web або системними адміністраторами,
можна використовувати оператора SELECT наступного вигляду:
Використання NOT перед IN дозволяє вивести дані, які не входять в множину, визначувану
умовою IN.
Оператор BETWEEN використовується для визначення цілочисельних меж. Тому замість age
>= 32 AND age <= 40 можна використовувати age BETWEEN 32 AND 40.
Що робить запит
SELECT f_name, l_name, title, age
from employee_data where
title NOT IN ('программист', 'старший программист',
'программист мультимедиа')
AND age NOT BETWEEN 28 and 32;
У міру збільшення таблиць виникає необхідність виводу тільки підмножини даних. Цього
можна добитися за допомогою пропозиції LIMIT.
Наприклад, щоб вивести з таблиці імена тільки перших п'яти співробітників,
використовується оператор LIMIT з аргументом рівним 5.
Можна з'єднати оператора LIMIT з оператором ORDER BY. Таким чином, наступний оператор
виведе четверо наймолодших співробітників компанії.
Щоб вивести всі посади бази даних компанії, можна виконати наступного оператора:
Робота з датою
Дати в MYSQL завжди представлені роком, за яким слідує місяць і потім день місяця. Дати
часто записують у вигляді YYYY-MM-DD, де YYYY -- 4 цифри року, MM -- 2 цифри місяця і DD
-- 2 цифри дня місяця.
Тип стовпця дати дозволяє виконувати декілька операцій, таких як сортування, перевірка
умов за допомогою операторів порівняння і так далі
Використання операторів = і !=
Визначення діапазонів
select e_id, birth_date from employee_per where
birth_date BETWEEN '1969-01-01' AND '1974-01-01';
Будьте уважні при використанні назв місяців, оскільки вони розрізняють регістр символів.
Тому January працюватиме, а JANUARY не буде!
Аналогічно можна вибрати співробітників, що народилися в певний рік або в певний день.
Поточна дата
Поточну дату, місяць і рік можна вивести за допомогою
аргументу CURRENT_DATE пропозицій DAYOFMONTH(), MONTH() і YEAR(), відповідно. Те ж
саме можна використовувати для вибірки даних з таблиць.
Математичні функції
Описані нижче функції виконують різні математичні операції. Як аргументи більшість з них
приймає числа з плаваючою комою і повертає результат аналогічного типа.
LOG(число1, число2) - при виклику з одним параметром функція LOG повертає натуральний
логарифм числа, а при виклику з двома параметрами - повертає логарифм числа2 по
підставі число1.
LOG(число1, число2) еквівалентна LOG(число2)/ LOG(число1).
PI() - повертає значення числа . За умовчанням відображується п'ять знаків після десяткової
коми, але внутрішньо MYSQL використовує повне представлення дійсного числа подвійної
точності.
ORDER BY RAND() у комбінації з LIMIT зручно для вибору випадкового прикладу з набору
рядків:
SIGN(число) - повертає знак аргументу як -1, 0 або 1, залежно від того, число негативне,
нуль або позитивне.
Індекси
Індексування (indexing) - це спосіб забезпечення швидкого доступу до значень колонки або
комбінації колонок. Фізично нові рядки додаються в кінець таблиці, результатом чого є
неврегульоване розміщення значень в колонках. Без використання яких-небудь методів
впорядкування даних єдиним способом проглядання значення колонки в є послідовний
перегляд кожного рядка від початку таблиці до її кінця, так зване сканування таблиці.
Продуктивність такого сканування пропорційно розміру таблиці, розміру фізичної сторінки
бази даних і довжині рядка.
Одним із способів внесення відношення порядку в значення колонок без порушення
фізичного розташування рядків таблиці є створення - індексу.
Індекс (index) - це об'єкт в реляційній базі даних, який призначений для організації
швидкого доступу до рядків таблиці по значеннях однієї або декількох колонок цього рядка
Про створення індексу ми вже говорили при обговоренні обмежень первинного ключа і
зовнішнього ключа. Тоді індекси призначалися для підтримки цілісності первинного ключа і
підтримки відношень. Зараз піде мова про використання індексу як інструменту підвищення
продуктивності обробки запитів.
Кожна таблиця бази даних може мати один або декілька індексів. Індекси можуть
створюватися по одній колонці або декільком колонкам таблиці. Колонки, що входять в
індекс, прийнято називати ключовими полями (key fields) або ключами. Індекси можуть бути
унікальними і неунікальними. Неунікальний індекс може мати декілька ключів з однаковими
значеннями.
Індекс B-Tree характеризується кількістю рівнів в індексі (height). Чим менше рівнів, тим
вище продуктивність.
Індекси створюються командою SQL CREATE INDEX.
Команда CREATE TABLE не відрізняється нічим від інших команд створення таблиць до тих
пір, поки не зустрінеться пропозиція ORGANIZATION INDEX, яка указує СУБД на створення
виключно індексної таблиці. Для розміщення індексу на диску указується табличний
простір. Параметр PCTTHRESHOLD указує, що частку рядка, що залишилася, потрібно
зберігати в заданому табличному просторі - сегменті переповнювання, якщо даний рядок
перевищує розмір фізичної сторінки бази даних на вказане число відсотків. Параметр
INCLUDING визначає ім'я колонки, з якою рядок індексної таблиці ділиться на дві частки:
індексну і переповнювання. Ця колонка може бути часткою первинного ключа таблиці або
неключовою колонкою. Всі неключові колонки, які слідують за вказаною колонкою,
розміщуються в сегменті переповнювання, який визначається ключовим словом OVERFLOW.
Секціонування
У багатьох базах даних в таблицях зберігається величезна кількість даних. Чим більше
розмір таблиці, тим більше часу буде потрібно як для деяких операцій по вибірці рядків
таблиці, так і для виконання деяких функцій адміністратора бази даних (резервного
копіювання і відновлення). Великі за розміром індексовані таблиці мають також великі
індекси, які вимагають багато часу СУБД для роботи з ними.
При здійсненні секціонування одним з важливих понять є колонка таблиці, щодо значень
якої СУБД робитиме те, що фізичне розноситься таблиці по різних табличних просторах на
жорстких дисках. Ці колонка називається ключем секціонування (partition key).
Секціонування по діапазону
Секціонування по діапазону (range partitioning) означає розподіл рядків таблиці на різні
табличні простори залежно від значення ключа секціонування. Доступ до такої таблиці, як
і до будь-якої іншої, здійснюється по її імені, причому доступ до секцій, розташованої в
кожному табличному просторі, можна отримати окремо.
Наприклад, таблицю, що містить фінансові квартальні звіти організації, можна секціонувати
по даті таким чином, що звіти по кожному кварталу зберігатимуться в окремому табличному
просторі. При такій організації секцій дані тільки по одному кварталу вибиратимуться з
одного табличного простору, що підвищить ефективність роботи бази даних в цілому.
Щоб дістати доступ до рядків таблиці, розташованих в певній секції, дізнатися про продажі
в третьому кварталі, можна використовувати команду SELECT, як показано нижче:
Хэш-секціонування
Хэш-секціонування (hash partitioning) означає рівномірний розподіл рядків таблиці по
табличних просторах залежно від значення ключа секціонування, який в даному випадку
хэшируется. Цей вид секціонування зручно застосовувати для рядків, у яких розподіл
значень ключа секціонування нерівномірно або погано групується. Якщо проектувальник
бази даних ухвалює рішення про створення хэш-секционированной таблиці, то він повинен
достатньо точно представляти розмір цієї таблиці, оскільки вбудовані в СУБД Oracle
алгоритми хешування використовують цей розмір для обчислення позиції рядка на фізичній
сторінці бази даних. Невірне визначення розміру таблиці може привести до великого числа
колізій, тобто до попадання рядків з різними значеннями ключа на одну і ту ж сторінку, що
приводить до підтримки ланцюжків переповнювання і додаткового введення/виводу.
Складене секціонування
Складене секціонування (composite partitioning) є комбінацією секціонування по діапазону
і хеш-секціонування. Це означає, що таблиця спочатку розподіляється серед табличних
просторів на основі діапазону значень ключа секціонування, далі кожна з отриманих секцій
діапазонів ділиться на підлеглі секції або підсекції, і потім рядки рівномірно розподіляються
серед підлеглих секцій за значенням хэш-ключа.
Кластери
Найповільнішою операцією, виконуваною СУБД, є операція читання даних з диска або запис
даних на диск. Якщо існує можливість зменшити у декілька разів число таких операцій, то
загальна продуктивність бази даних може помітно збільшитися.
Слід пам'ятати, що СУБД прочитує з диска або записує на диск за один раз одну фізичну
сторінку даних, розмір якої коливається залежно від апаратної платформи від 512 байт до 4
Кб. Таким чином, якщо можна фізично зберігати дані, до яких часто відбувається сумісне
звернення, на одній і тій же сторінці диска або на сторінках, фізично близько розташованих
один до одного, то швидкість доступу до цих даних підвищується.
З фізичної точки зору кластер знаходиться окремо від таблиць. Він створюється з вказівкою
параметрів зберігання, а потім в нім послідовно створюються кластеризовані таблиці. При
описі кластера потрібно вказати колонки або колонку, для яких СУБД сформує кластер, і
таблиці, які будуть включені в його склад. При обробці даних СУБД розміщуватиме рядки,
що містять однакові значення в колонках кластера, фізично максимально близько. В
результаті рядка таблиці можуть бути розподілені серед декількох дискових сторінок, але
первинні і зовнішні ключі зазвичай розташовуються на одній сторінці.
Транзакції
1. Паралельні запити
2. Транзакції
3. Проблеми паралельного доступу з використанням транзакцій
4. Рівні ізоляції
5. Визначення параметрів транзакції
6. Блокування
Паралельні запити
СУБД є багатопотоковою програмою, тому вимушена справлятися з множинними запитами
на підключення. Але окрім проблеми планування виникає ще і проблема
одночасного(паралельного) доступу до данних
Проте, нe всяку послідовність операцій можна виразити у вигляді одного запиту. Скажімо,
для оновлення двох таблиць необхідно два запити. У таких випадках потрібно явно
вказувати початок і кінець кожної трансакції.
Транзакції
Транзакцією називається послідовність дій, яка або повністю фіксується в базі даних, або
повністю відміняється. Інколи під транзакцією також мають на увазі не групу SQL-
операторов, а інтервал часу, протягом якого всі виконувані SQL-оператори можна або
зафіксувати або відмінити.
Так, операція переказу грошей з одного рахунку на іншій повинна складати єдину
транзакцію. Інакше може виникнути ситуація, коли перший SQL-оператор перекладе гроші
на інший рахунок, а другий, виконуючий зняття їх з рахунку, не доведе справу до кінця із-
за непередбаченого збою.
Транзакції реалізуються шляхом ведення журналу всіх змін, що вносяться до бази даних в
ході кожної транзакції. Коли відбувається відкат, СУБД звіряється з журналом і відміняє всі
зміни. По журналу легко можна відновити узгоджений стан бази даних в разі збою.
Неповторюване читання
Припустимо, є дві транзакції, відкриті різними застосуваннями, в яких виконані наступні
SQL-операторы:
Транзакція 1 Транзакція 2
SELECT f2 FROM tbl1 WHERE f1=1; SELECT f2 FROM tbl1 WHERE f1=1;
UPDATE tbl1 SET f2=f2+1 WHERE f1=1;
SELECT f2 FROM tbl1 WHERE f1=1;
У транзакції 2 вибирається значення поля f2, потім в транзакції 1 змінюється значення поля
f2. При повторній спробі вибору значення з поля f2 в транзакції 1 буде отримано інший
результат. Ця ситуація особливо неприйнятна, коли дані прочитуються з метою їх часткової
зміни і зворотного запису в базу даних.
"Брудне" читання
Припустимо, є дві транзакції, відкриті різними застосуваннями, в яких виконані наступні
SQL-операторы:
Транзакція 1 Транзакція 2
SELECT f2 FROM tbl1 WHERE f1=1;
UPDATE tbl1 SET f2=f2+1 WHERE f1=1;
SELECT f2 FROM tbl1 WHERE f1=1;
ROLLBACK WORK;
Втрачене оновлення
Припустимо, є дві транзакції, відкриті різними застосуваннями, в яких виконані наступні
SQL-операторы:
Транзакція 1 Транзакція 2
SELECT f2 FROM tbl1 WHERE f1=1; SELECT f2 FROM tbl1 WHERE f1=1;
UPDATE tbl1 SET f2=20 WHERE f1=1;
UPDATE tbl1 SET f2=25 WHERE f1=1;
У транзакції 1 змінюється значення поля f1, а потім в транзакції 2 також змінюється значення
цього поля. В результаті зміна, виконана першою транзакцією, буде втрачена.
Фантомна вставка
Припустимо, є дві транзакції, відкриті різними застосуваннями, в яких виконані наступні
SQL-операторы:
Транзакция 1 Транзакция 2
SELECT SUM(f2) FROM tbl1;
INSERT INTO tbl1 (f1,f2) VALUES (15,20);
SELECT SUM(f2) FROM tbl1;
Рівні ізоляції
Теоретично СУБД повинна забезпечувати повну ізоляцію транзакцій. На практиці ж
вводиться декілька рівнів ізоляції, найвищий з яких відповідає повній ізольованості.
У стандарті мови SQL визначено чотири рівні ізоляції: READ UNCOMMITTED, READ
COMMITTED, REPETABLE READ і SERIALIZABLE. Вони перераховані в порядку від найменшої
до найвищої ізольованості і по черзі вирішують три основне проблеми, що виникають при
використанні транзакцій: поява проміжних даних, поява неузгоджених даних і поява рядків-
примар.
Проміжні дані з'являються, коли незавершена транзакція модифікує рядок таблиці, а інша
транзакція читає цей рядок. Якщо перша транзакція буде скасована (станеться відкат), то
виявиться, що друга транзакція отримала дані, які офіційно ніколи не існували. Така
поведінка виявляється на рівні READ UNCOMMITTED.
У режимі READ COMMITTED транзакціям дозволено читати тільки підтверджені дані. Проте
це не вирішує проблему неузгоджених даних. Припустимо, в ході транзакції вводиться
запит, що визначає число записів в таблиці. Після закінчення цього запиту інша транзакція,
що працює з тією ж самою таблицею, видаляє або додає записи. Якщо тепер перша
транзакція повторно виконає свій запит, вона отримає інші результати.
Проблема неузгоджених даних вирішується на рівні REPEATABLE READ. У цьому режимі
рядки, до яких транзакція звертається для читання або запису, блокуються. Але і тут є
проблема: стрічки-примари. Транзакція може заблокувати всі записи, з якими ведеться
робота, але вона не може перешкодити іншій транзакції додати рядки в ту ж саму таблицю.
Якщо в ході транзакції вводяться два запити на вибірку, а між ними друга транзакція додає
в таблицю новий рядок, цей рядок стане "фантомом", оскільки він раптово з'являється в
ході однієї і тієї ж транзакції.
У режимі SERIALIZABLE транзакції примусово виконуються одна за одною. Саме така
поведінка рекомендується в стандарті SQL. Якщо дві транзакції спробують відновити один і
той же рядок, одна з них буде оголошена такою, що програла в тупиковій ситуації і як
наслідок - скасована.
Блокування
Користувачеві найчастіше не потрібно робити ніяких дій по управленню блокуваннями. Всю
роботу по установці, зняттю і вирішенню конфліктів виконує спеціальний компонент
сервера, званий менеджером блокувань. MS SQL Server підтримує різні рівні блокування
об'єктів (або деталізацію блокувань), починаючи з окремого рядка таблиці і закінчуючи
базою даних в цілому. Менеджер блокувань автоматично оцінює, яку кількість даних
необхідно блокувати, і встановлює відповідного типа блокування. Це дозволяє підтримувати
рівновагу між продуктивністю роботи системи блокування і можливістю користувачів
діставати доступ до даних. Блокування на рівні рядка дозволяє найточніше управляти таким
доступом, оскільки блокуються тільки дійсно змінні рядки. Безліч користувачів можуть
одночасно працювати з даними з мінімальними затримками. Платою за це є збільшення
числа операцій установки і зняття блокувань, а також велика кількість службової інформації,
яку доводиться зберігати для відстежування встановлених блокувань. При блокуванні на
рівні таблиці продуктивність системи блокування різко збільшується, оскільки необхідно
встановити лише одне блокування і зняти її тільки після завершення транзакції. Користувач
при цьому має максимальну швидкість доступу до даних. В той же час вони не доступні
нікому іншому, тому що вся таблиця заблокована. Доводиться чекати, поки поточний
користувач завершить роботу.
Дії, що виконуються користувачами при роботі з даними, зводяться до операцій двох типів:
їх читанню і зміні. У операції по зміні включаються дії з додавання, видалення і власне зміни
даних. Залежно від виконуваних дій сервер накладає певний тип блокування з наступного
переліку:
· Колективні блокування. Вони накладаються при виконанні операцій читання даних
(например,SELECT). Якщо сервер встановив на ресурс колективне блокування, то
користувач може бути упевнений, що вже ніхто не зможе змінити ці дані.
· Блокування оновлення. Якщо на ресурс встановлено колективне блокування і для
цього ресурсу встановлюється блокування оновлення, то ніяка транзакція не зможе
накласти колективне блокування або блокування оновлення.
· Монопольне блокування. Цей тип блокувань використовується, якщо транзакція
змінює дані. Коли сервер встановлює монопольне блокування на ресурс, то ніяка інша
транзакція не може прочитати або змінити заблоковані дані. Монопольне блокування не
сумісне ні з якими іншими блокуваннями, і жодне блокування, включаючи монопольну, не
може бути накладена на ресурс.
· Блокування масивного оновлення. Накладається сервером при виконанні
операцій масивного копіювання в таблицю і забороняє звернення до таблиці будь-яким
іншим процесам. В той же час декілька процесів, що виконують масивне копіювання, можуть
одночасно вставляти рядки в таблицю.
Окрім перерахованих основних типів блокувань SQL Server підтримує ряд спеціальних
блокувань, призначених для підвищення продуктивності і функціональності обробки даних.
Вони називаються блокуваннями намірів і використовуються сервером в тому випадку, якщо
транзакція має намір дістати доступ до даних вниз за ієрархією і для інших транзакцій
необхідно встановити заборону на накладення блокувань, які конфліктуватимуть з
блокуванням, першою транзакцією, що накладається.
Блокування, що раніше розгледіли, відносяться до даних. Окрім перерахованих в середі SQL
Server існує два інших типа блокувань: блокування діапазону ключів і блокування схеми
(метаданих, що описують структуру об'єкту).
Блокування діапазону ключів вирішує проблему виникнення фантомів і забезпечує вимоги
серіалізованості транзакції. Блокування цього типа встановлюються на діапазон рядків,
відповідних певній логічній умові, за допомогою якої здійснюється вибірка даних з таблиці.
Блокування схеми використовується при виконанні команд модифікації структури таблиць
для забезпечення цілісності даних.
Востаннє редаговано: Понеділок, 2 вересня 2019, 10:16. Версія: 0. Опубліковано: Понеділок, 22
жовтня 2012, 18:00.
Кожен програмний компонент має власне уявлення про систему. СУБД MYSQL розглядує дані
як інформаційні блоки файлів на диску. Додатки працюють з даними як із записами, які
повертаються в результаті SQL запитів.
На мал. 8.2 приведена діаграма відношень між чотирма таблицями. У цих таблицях
зберігаються відомості про адреси, клієнтів, замовлення і товари. Кожен прямокутник є
таблицею. Лінії, що сполучають таблиці, показують відношення "зовнішній ключ -
первинний ключ". Між таблицями клієнтів і замовлень існує відношення "один до багатьом".
Клієнт може зробити довільне число замовлень (зокрема жодного), але будь-яке замовлення
належить тільки одному клієнтові. Кружок на діаграмі говорить про те, що відношення є
необов'язковим.
У замовлення включається один або декілька товарів. Звернете увагу на відношення "багато
до багатьом". Логічно кожне замовлення пов'язане з групою товарів, а один і той же товар
може входити в декілька замовлень.
Реляційна модель не дозволяє безпосередньо формувати відношення "багато до багатьом".
В ході етапу проектування це відношення перетвориться таким чином, що з'явиться
проміжна таблиця. У таблицю адрес винесені стовпці, загальні для таблиць замовлень і
клієнтів. У таблиці замовлень указується адреса доставки, якщо замовлення робиться через
Web_вузол. У таблиці клієнтів приводяться їх основні адреси, використовувані при
безпосередньому спілкуванні з клієнтами. Наявність таблиці адрес дозволяє гарантувати,
що всі адреси матимуть однакову структуру.
На фізичному рівні описується архітектура системи. Діаграми цього рівня відображають
взаємодію апаратних компонентів. Тут можуть бути представлені мережеві з'єднання, а
також канали запису даних в постійні сховища.
Відношення "один до багатьом" між таблицями категорій і товарів. Читається так: "у кожну
категорію входить один або декілька товарів" або "кожен товар належить до однієї і лише
до однієї категорії".
Відношення між об'єктами можуть бути необов'язковими. Щоб показати це, на лінії поряд з
символом відношення ставлять незаштрихований кружок.
Необов'язкове відношення між таблицями замовлень і адрес. Воно читається таким чином:
"у замовленні може бути вказана одна адреса" або "кожна адреса належить до одного
замовлення".
Реалізація моделі
Коли проект бази даних завершений, переходять до її реалізації. Відповідно до діаграм
створюються інструкції CREATE TABLE. Будьте готові повернутися до етапу проектування
для внесення чергових модифікацій: перехід на мову SQL часто відкриває різні упущення.
Всі SQL_инструкции, що створюють базу даних, мають бути зведені в одному або декількох
текстових файлах, а не вводитися в інтерактивному режимі. Це дозволить стирати базу
даних і створювати її "з нуля". Ці ж файли послужать як документація. Перед кожною
інструкцією CREATE TABLE вставляється коментарі, що пояснюють призначення таблиці.
Коментарі ігноруються синтаксичним аналізатором, тому вони не зберігаються в базі даних,
зате дають можливість людині, супроводжуючій базу даних, зрозуміти її структуру. (“//’, “/*
*/”)
Можна також користуватися опцією COMMENT інструкції CREATE TABLE.
При переході від етапу проектування до етапу реалізації необхідно дотримуватися п'яти
ключових принципів:
• первинні ключі слід позначати специфікатором NOT NULL;
• користуйтеся флагом AUTO_INCREMENT для автоматичного створення ідентифікаторів;
• зовнішні ключі повинні посилатися на первинні ключі;
• відношення "багато до багатьом" повинні встановлюватися через проміжну таблицю;
• таблиці, між якими існують стосунки "один до одного", краще об'єднувати.
Як правило, всяка таблиця повинна мати первинний ключ. Стовпці первинних ключів
необхідне об’являти із специфікатором NOT NULL. У більшості таблиць первинним ключем є
окремий стовпець цілочисельних значень, оскільки частенько важко сказати заздалегідь,
чи будуть значення інших полів унікальними.
Зовнішні ключі беруть участь в відношеннях "один до багатьом". Таблиця, з якою існує
"множинний" зв'язок, міститиме зовнішній ключ, вказуючий на первинний ключ протилежної
таблиці. MYSQL не перевіряє правильність значень зовнішніх ключів, тобто пропозиції
FOREIGN KEY інструкції CREATE TABLE є необов'язковими.
Якщо на діаграмі присутні стосунки "багато до багатьом", кожне з них має бути перетворене
в два відношення "один до багатьом" з проміжною таблицею. Первинні стовпці початкових
таблиць перетворяться в зовнішні ключі проміжної таблиці. Це означає, що у неї будуть два
цілочисельні стовпці.
Перевірте доцільність відношень "один до одного". Бувають випадки, корду вони дійсно
необхідні, але, можливо, ви просто пропустили можливість злиття двох таблиць.
Стовпці, що зберігають грошові величини, повинні мати типа DECIMAL. Це тип чисел з
фіксованою кількістю цифр після коми. У MYSQL десяткові числа зберігаються в строковому
вигляді і не підлягають апроксимації, на відміну від інших типів чисел з плаваючою комою.
Ефект апроксимації приводить до того, що числа, що відрізняються на дуже незначну
величину, виявляються рівними. В разі порівняння грошових сум це може означати
незаплановану втрату грошей.
Значення типа DECIMAL перетворяться із строкової форми в числа з плаваючою комою при
виконанні математичних операцій. Щоб захистити себе від помилок апроксимації, виконуйте
ці операції в додатках.
Тестування
Тестування буває двох видів: на предмет пошуку недоліків і на предмет перевірки повноти
реалізації. Недоліки є наслідком людських помилок. За повну вважається система, що
задовольняє всім початковим вимогам.
На підставі специфікації вимог і специфікації проекту провіряються всі функціональні
можливості, реалізовані в базі даних. Потрібно переконатися, що всій інформаційній суті
поставлені у відповідність таблиці або стовпці. Виконаєте ряд типових операцій над базою
даних і переконаєтеся в отриманні очікуваних результатів.
Пошук недоліків спочатку здається легким завданням, і лише згодом з'ясовується, що це не
так. Синтаксичні помилки SQL_запитів виявляються відразу ж і швидко виправляються, але
є помилки, які виявляються лише в певних ситуаціях. Наприклад, об'єднання двох таблиць
без індексу виконується швидко при малій завантаженості системи. Проте коли 20
користувачів одночасно виконують один і той же запит, продуктивність падає нижче за
критичну відмітку.
Якщо в початкових вимогах обумовлені обмеження продуктивності, буде потрібно спеціальні
програми, які викличуть високу завантаженість бази даних. Тільки так можна буде
перевірити її роботу в екстремальних умовах.
У пакет MYSQL входять спеціальні утиліти тестування, що дозволяють вимірювати
продуктивність сервера. Вони є Perl_сценарії, що знаходяться в каталозі sql_bench
дистрибутива.
Визначення функцій
При розробці ієрархії функцій аналітик повинен надати текстовий опис до кожної функції, у
крайньому випадку для верхнього і найнижчого рівнів ієрархії. Бажано, щоб у цьому описі
аналітики виділяли сутності предметної області. Це важливо для того, щоб знати з якими
сутностями предметної області працює функція, тобто які потенційні об’єкти реляційної бази
даних будуть використовуватися в кожній функції. Якщо це не зроблено, то
проектувальнику бази даних прийдеться робити це самостійно.
Приклад. Визначення функції "2.2.2. Перевірити чи забезпечена заява".
"Отримати і зареєструвати всі потрібні страховій компанії свідчення про заяву (СВІДЧЕННЯ
ПРО ЗАЯВУ), включаючи всі детальні свідчення про треті сторони (СТОРОННІ ЮРИДИЧНІ
ОСОБИ) і свідків (ФІЗИЧНІ ОСОБИ).
Вивчити страховий поліс (ПОЛІС) на предмет наявності виключень (ВИКЛЮЧЕННЯ) і
визначити, чи діють ці виключення у випадку даної заяви (ЗАЯВА).
Якщо є виключення, то закрити заяву і скласти стандартний лист заявнику про відмову у
виплаті (ЛИСТ) заявнику (ЗАЯВНИК).
Якщо ніяких виключень немає, то змінити статус заяви на очікування оцінки, назначити і
повідомити оцінника (ОЦІННИК). "
З прикладу видно, які сутності предметної області беруть участь у виконанні функції
(виділені в дужках), як міняється стан сутності (виділено курсивом) і який алгоритм роботи
цієї функції.
З прикладу ясно, що на цьому етапі проектувальник бази даних у якості вхідних даних
використовує також інформаційну модель предметної області бази даних (опис сутностей).
При виконанні аналізу функцій корисно мати якусь таблицю (матрицю) "Функція-Сутність".
Ця матриця повинна дати відповідь на такі питання:
чи є у кожної сутності конструктор (функція, яка створює всі екземпляри сутності);
чи є у неї деструктор (функція, яка видаляє екземпляри сутності);
чи є ссилка на цю сутність (функції, які використовують цю сутність і яким чином)
<
Таким чином отримаємо список функцій, який показаний в лівій колонці таблиці. Цьому
списку функцій повинен бути поставлений у відповідність список модулів застосувань бази
даних.
Проектувальник бази даних склав список модулів застосувань бази даних (права колонка
таблиці) і встановив відображення функцій в модулі, як показано на рисунку.
Job Зчитування
Sal Зчитування
Manager Зчитування
Системні модулі
Як було вказано раніше, ціль проектувальника модулів – реалізація функціональних
можливостей, які задовольняють бізнес-вимоги, викладені в функціональній моделі
предметної області бази даних. Проте при цьому необхідно розглянути достатню кількість
процесів, які не витікають безпосередньо із сформульованих бізнес-функцій. Наприклад,
можливість видачі результатів роботи модуля у файл чи на принтер.
Набір модулів застосувань бази даних, який не витікає безпосередньо з бізнес-функцій, але
необхідний для забезпечення роботи системи, називається системним.
До таких модулів можна віднести процедури резервного копіювання і автоматичного
відновлення, модулі, які надають користувачам можливість змінювати свій пароль, модулі
друку, модулі навігації по додатках бази даних і т.д.
Проектувальник бази даних самостійно розробляє специфікації таких модулів.
В цьому розділі ми розглянемо деякі фактори, які повинні враховувати проектувальники баз
даних при розмежуванні управління інтерфейсом застосувань користувача і виконання
операцій обробки даних в модулях.
Як відзначають спеціалісти в області розробки і проектування інформаційних систем, багато
недоліків в прикладних системах викликані тим, що в них не визначені
розбіжності між правилами для даних, правилами для процесів і правилами для
інтерфейсу. Розглянемо основні з них.
Правила для даних. В правилах для даних формулюються умови, які повинні задовольняти
дані. Ці правила діють для кожного екземпляра даних і виводяться із моделі даних.
Приклади правил для даних:
Стать людини має бути або чоловічою, або жіночою. Це правило може бути введене
за допомогою обмеження CHECK у визначенні колонки таблиці бази даних.
Кожне замовлення має бути призначене для одного і тільки одного покупця. Це
правило для даних може бути введене за допомогою
обмежень PRIMERY KEY або NOT NULL
Правила для інтерфейсу. В правилах для інтерфейсу встановлюється, яким повинен бачити
користувач застосування. Ці правила не стосуються обробки, а лише впливають на
уявлення користувача про застосування бази даних. Ці правила виводяться в специфікації
інтерфейсу користувача.
Приклади правил для інтерфейсу:
Всі коди валют повинні бути пояснені. Це специфікація замовника до візуалізації
кодів валют.
Номера відділів і підрозділів не мають показуватися. Це також є вимогою замовника
системи відносно візуалізації даних в додатку.
Наприклад. В якості прикладу наведемо специфікацію екранної форми для роботи з базою
даних через браузер.
Ім’я екранної форми: Web-сторінка Форма 3: Список виконавців.
Ціль: приписати виконавців до проекту, визначити їх зайнятість і статус.
Вхідні дані
Номер проекту
Навігація:
Викликається із модуля "Редагування Форми 1".
Повертає управління в модуль "Редагування Форми 1".
Дії:
Вибрати зі списку виконавця
Визначити його статус - основний, неосновний, керівник
Визначити зайнятість виконавця
Зберегти запис про виконавця
Перейти на введення даних про наступного
Повернутись на Редагування Форми 1.
Таблиці:
Таблиця tblProjEMP
NM ПІБ INSERT
PS Посада
GR Розряд
DR Науковий ступінь
ZV Вчене звання
Таблиця tblEmpl
PS Посада
GR Розряд
DR Науковий ступінь
ZV Вчене звання
Помилки:
Повторне введення даних форми в базу даних вважається помилкою. Повинні
бути передбачені дії, які блокують повторне введення даних форми.
Як видно з обговорення і наведених прикладів, хороша специфікація
модуля повинна повідомити всім, що цей модуль повинен робити, а не як саме він повинен
це робити. Виділене курсивом слово "всім" означає не тільки безпосередніх учасників
проекту (керівника, програмістів, компонувальників і тестувальників), але також і
аналітиків, керівників вищої ланки, представників замовника.
Проектування процесу тестування модулів застосувань
Тестування додатку бази даних є одним із основних елементів підготовки і проведення
приймально-здавальних випробувань. Як показує практика, планування тестування
застосувань бази даних повинно починатися ще на стадії аналізу. Існує імовірність того, що
замовник може відмовитись від раніше прийнятих критеріїв випробувань в процесі
виконання проекту. Проте частіш за все планування тестування відкладають до етапу
проектування, і, таким чином, складання плану тестування стає завданням
проектувальника бази даних чи адміністратора бази даних.
В процесі тестування повинно бути з’ясовано, що застосування бази даних робить те, що
від нього вимагається, тобто відповідає сформульованим вимогам приймально-здавальних
випробувань.
Як правило, в процесі проектування проектувальник бази даних пропонує стратегію (чи
план) комплексного і системного тестування. При розробці стратегії тестування варто
пам’ятати про те, що повинні використовуватися тести таких категорій:
Автономні тести (тести модулів).
Тести зв’язків модулів.
Системний тест для додатку бази даних в цілому.
Приймально-здавальні випробування (які може проводити замовник).
Тести продуктивності.
Завдання рольового кластера "Тестування" (test) - схвалення випуску продукту тільки після
того, як всі дефекти виявлені и улагоджені. Будь-яке програмне забезпечення містить
дефекти. Виявлення і усунення дефектів може означати різні рішення, починаючи від
усунення і закінчуючи документуванням способів обходу дефекту. Поставка продукту з
відомим дефектом, але з описом способів його обходу є кращою, ніж поставка продукту з
невиявленим дефектом, який в подальшому стане сюрпризом - як для проектної команди,
так і для замовника.
Щоб досягти успіху, команда тестувальників повинна сфокусуватися на певних ключових
завданнях. Вони структуруються у вигляді трьох областей компетенції.
1. Планування тестів:
o розробка методології і плану тестування;
o участь у встановленні стандарту якості (quality bar);
o розробка специфікацій тестів.
2. Розробка тестів:
o розробка і підтримка автоматизованих тестів (automated test cases),
інструментів і скриптів;
o проведення тестів з ціллю визначення стану проекту;
o управління білдами (manage the build process).
3. Звітність про тести:
o доведення до відома проектної групи інформації про якість продукту;
o моніторинг знайдених помилок з метою забезпечення їх залагодження до
випуску продукту.
Розробка прикладного
програмного
забезпечення для бази
даних
Сюди відносяться:
Збережені процедури (Stored Procedures)
Визначені користувачем функції (User-defined
Functions або UDFs))
Тригери (Triggers)
Stored procedures
Збережені процедури є об'єктами СУБД, які можуть
інкапсулювати SQL запити і бізнес-логіку.
User-defined functions
Визначені користувачем функції (UDF) є об'єктами бази
даних, які дозволяють користувачам розширити SQL
мову.
Приклад тригера
Client-side development
Розробка клієнтської частини (Client-side
development), це написання застосувань, які
запускаються на стороні клієнта,
а потім отримують доступ до бази даних за допомогою п
рограмних інтерфейсів (API).
OLE DB
Object Linking and Embedding, Database (OLE DB)
являє собою набір інтерфейсів, що забезпечують доступ
до даних, що зберігаються в різних джерелах. Він був
розроблений в якості заміни ODBC та розширений для
підтримки більшої кількості джерел інформації, у тому
числі й не реляційних баз даних
OLE DB реалізований з використанням COM технології.
ADO.NET
ActiveX Data Objects (ADO) - об'єкти даних ActiveX
прикладний програмний інтерфейс для доступу до
даних, розроблений компанією Microsoft і заснований на
технології компонентів ActiveX. ADO дозволяє
представляти дані з різноманітних джерел: (реляційної
СУБД, текстових файлів тощо) в об'єктно-орієнтованому
програмуванні виді.
ORM
Object-relational mapping ( Об'єктно-реляційна
проекція) технологія програмування, яка зв'язує бази
даних з концепціями об'єктно-орієнтованих мов
програмування, створюючи віртуальну об'єктну базу
даних.
Розробка прикладного
програмного забезпечення для
роботи з СУБД на мові Java
The big picture
Переконатися в наявності
- JDK (розробник) або JRE(клієнт)
- коректного налаштувати JDK_PATH та JRE_PATH
- JDBC/SQLJ driver
- коректного налаштування CLASSPATH
Драйвера
Тип Імя драйвера Опис
Type 1 The JDBC-ODBC bridge driver Для доступу використовується O
Type 2 The Native-API driver Вимагає встановлення на ма
програмного забезпечення
інформацією з СУБД
Type 3 The JDBC net pure-java driver Чистий Java клієнт, який бе
сервером використовуючи СУБД
Type 4 The native-protocol pure-java Найбілш гнучкий дравер, який
driver. безпосередні зверення до СУБД
JDBC application using the type 2 driver
JDBC application using the type 4 driver
class myprg {
Drivers:
MySQL com.mysql.jdbc.Driver
MS SQL
Server com.microsoft.jdbc.sqlserver.SQLServerDriver
Oracle DB oracle.jdbc.driver.OracleDriver
Type 4 syntax:
import java.sql.*;
class myprg {
MySQL Jdbc:mysql://<ip>:3306/<dbname>
MS SQL
Server jdbc:Microsoft:sqlserver://<ip>:1433/<dbname>
Oracle jdbc:thin:@<server-id>:1521/dbname
Виконання UPDATE з
використанням executeUpdate
(1) PreparedStatement pStmt = con.prepareStatement
("UPDATE employee "
+
" SET salary = ? "
+
" WHERE empno = ?
");
(2) pStmt.setInt (1,85000);
(3) pStmt.setString(2,"000010");
(4) int numRows = pStmt.executeUpdate();
System.out.println("Number of rows updated:
" + numRows);
pStmt.close();
Збережувана процедура
CallableStatement cstmt;
(1) cstmt = con.prepareCall("call
high_paid_employees(?)");
(2) cstmt.setInt(1,80000);
(3) ResultSet rs = cstmt.executeQuery();
System.out.println("High-paid employees list\n" +
"------------------------");
(4) while ( rs.next() ) {
System.out.println( rs.getString(1) + " " +
rs.getString(2) );
}
rs.close();
cstmt.close();
Властивості ResultSet,
Властивості Опис
resultSetType Задає можливість прокручування
resultSetConcurrency Задає властивість оновлення
resultSetHoldability Позначає, що вибірка має
залишатися доступною навіть
після закінчення роботи із
запитом
Перевантажені конструктори
Використання ResultSet
(4) rs.updateString(2,"Shipped");
(5) rs.updateRow();
}
}
(6) rs.beforeFirst();
System.out.println("Printing all the purchase
order record status");
while(rs.next()) {
int id = rs.getInt(1);
String info = rs.getString(2);
System.out.println("id="+id+" info="+ info
);
}
try { con.rollback();}
catch (Exception e) { }
System.exit(1);
}
Statement stmt=con.createStatement();
stmt.executeUpdate("delete from product where
pid='101'");
SQLWarning sqlwarn=stmt.getWarnings();
while(sqlwarn!=null)
{
System.out.println ("Warning description: " +
sqlwarn.getMessage());
System.out.println ("SQLSTATE: " +
sqlwarn.getSQLState());
System.out.println ("Error code: " +
sqlwarn.getErrorCode());
sqlwarn=sqlwarn.getNextWarning();
}
Крок 5 Закриття зєднання
try{
Connection con =
DriverManager.getConnection(url,userID,p
asswd);
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery
("SELECT EMPNO, FIRSTNME, LASTNAME " +
" FROM EMPLOYEE " +
" WHERE SALARY > 80000" );
while ( rs.next() ) {
. . . . . . . . . . . . . . .
}
rs.close();
stmt.close();
con.close();
} catch (Exception e) {
e.printStackTrace();
}
Синтаксис SQLJ
Наприклад
Connection context
Для роботи з SQL через SQLJ спочатку треба встановити
контекст зєднання з СУБД
class myprg3 {
public static void main(String argv[]) {
try {
Connection con = null;
Class.forName("com.ibm.db2.jcc.DB2Driver");
String url = "jdbc:db2://127.0.0.1:50000/SAMPLE";
if (argv.length == 2) {
String userID = argv[0];
String passwd = argv[1];
con = DriverManager.getConnection(url,userID,passwd);
}
else { throw new Exception
("\n Usage: java myprg3 userID password\n");
}
(3) DefaultContext ctx = new DefaultContext(con);
(4) DefaultContext.setDefaultContext(ctx);
(5) if( ctx != null )
(6) { ctx.close();}
} catch (Exception e) { }
}
}
Execution contexts
Контекст виконання здійснює моніторинг і контроль за
виконанням SQL запитів.
Це еквівалент Statement в JDBC
Приклад:
Ітератори
Ітератори (Iterators) це еквівалент ResultSet в JDBC.
Приклад:
#sql public iterator positionIterator (int, String);
Class.forName("com.ibm.db2.jcc.DB2Driver").newInstanc
e();
Connection con=DriverManager.getConnection(url);
con.setAutoCommit(false);
(1) ctx ctx1=new ctx(con);
positionIterator iterator;
Statement stmt = con.createStatement();
ResultSet rs=stmt.executeQuery("select poid, status
from purchaseorder");
(2) #sql [ctx1] iterator={cast :rs};
#sql {fetch :iterator into :poid, :status};
while(!iterator.endFetch()) {
System.out.println("id: "+poid+" status: "+status);
#sql {fetch :iterator into :poid, :status};
}
iterator.close();
Розширення файлів:
Function Operation
AddEmployeeInfo( ) INSERT new employee information in the
table
UpdateEmployeeInfo( UPDATE employee salary into the table
)
FetchEmployeeInfo( ) SELECT employee information from the
table
DeleteEmployeeInfo( ) DELETE employee information from the
table
Підключення необхідних заголовкових
файлів
Оголошення змінних
(host variables)
int AddEmployeeInfo() {
int rc = 0;
printf("\n=========================");
printf("\n ADD EMPLOYEE INFORMATION");
printf("\n=========================");
(1) EXEC SQL INSERT INTO employee
(empno, firstnme, lastname, edlevel, salary)
VALUES (50001, 'RAUL', 'CHONG', 21, 6000),
(50002, 'JAMES', 'JI', 20, 5786),
(50003, 'MIN', 'YAO', 20, 5876),
(50004, 'IAN', 'HAKES', 19, 5489),
(50005, 'VINEET', 'MISHRA', 19,5600);
(2) if(SQLCODE < 0) {
printf ("\n ERROR WHILE ADDING EMPLOYEE
INFORMATION");
printf ("\n RETURNED SQLCODE = %d", SQLCODE);
rc = -1
} else {
printf("\n EMPLOYEE ADDED SUCESSFULLY ");
EXEC SQL COMMIT;
}
return rc;
}
int FetchEmployeeInfo() {
int rc = 0;
/* open cursor */
(2) EXEC SQL OPEN cur1;
/* fetch cursor */
(3) EXEC SQL FETCH cur1
INTO :hempno, :hfirstname, :hlastname, :hedlevel,
:hsalary ;
printf("\n\nEMPNO FIRSTNAME LASTNAME EMPSALARY");
printf("\n----- --------- -------- -----------
\n");
int UpdateEmployeeInfo() {
int rc = 0, noofemp, loop;
printf("\n============================");
printf("\n UPDATE EMPLOYEE INFORMATION");
printf("\n============================");
int DeleteEmployeeInfo() {
int rc = 0;
int option;
char diagoption;
printf("\n============================");
printf("\n DELETE EMPLOYEE INFORMATION");
printf("\n============================");
printf("\n ENTER 1: (TO DELETE EMPLOYEE
INFORMATION) ");
printf("\n ENTER 2: (TO DELETE ALL EMPLOYEES
INFORMATION) ");
scanf("\n%d", &option);
if(option == 1) {
} else {
(2) EXEC SQL DELETE employee WHERE empno BETWEEN
50001 AND 50005;
if(SQLCODE < 0) {
printf ("\n EROROR WHILE DELETING INFORMATION");
printf ("\n RETURNED SQLCODE = %d", SQLCODE);
rc = -1;
exit(1);
}
Підтвердження запитів
Після виконання SQL запиту, в залежності від логіки
роботи вашої програми, потрібно здійснити commit або
rollback.
EXEC SQL COMMIT;
if (SQLCODE < 0) {
printf ("\n COMMIT ERROR");
printf ("\n SQLCODE = %d", SQLCODE);
exit(1);
}
Кроки
1. Здійснити прекомпіляцію програми
використовуючи команду PRECOMPILE
2. Якщо ви використовуєте файл звязку (опція
BINDFILE для прекомпілятора), необхідно звязати цей
файл з СУБД для створення програмного пакету
використовуючи команду BIND.
3. Скомпілювати змінений код програми і код що не
містить вбудованого SQL та отримати обєктний файл
(.obj).
4. Злінкувати отриманий обєктний файл з
бібліотеками СУБД і створити виконуваний файл (.exe)
Розробка програм на C/C++ з використанням
ODBC/CLI
Handles
SQLRETURN SQLAllocHandle(
SQLSMALLINT HandleType, // тип
дескприптора
SQLHANDLE InputHandle, // вхідний
дескриптор
SQLHANDLE *OutputHandlePtr); // вихідний
дескриптор
Результат виконання:
SQL_SUCCESS
SQL_SUCCESS_WITH_INFO
SQL_INVALID_HANDLE
SQL_ERROR
Приклад отримання дескриптора оточення
SQLRETURN SQLConnect (
SQLHDBC ConnectionHandle, /* hdbc */
SQLCHAR *ServerName, /* szDSN */
SQLSMALLINT ServerNameLength, /* cbDSN */
SQLCHAR *UserName, /* szUID */
SQLSMALLINT UserNameLength, /* cbUID */
SQLCHAR *Authentication, /* szAuthStr */
SQLSMALLINT AuthenticationLength /* cbAuthStr */
);
printf("\n\nConnected to %s database
successfully\n", dbAlias);
SQLDriverConnect() API
CLI API
Function Description
SQLPrepare Підготувати запит
SQLSetParam Встановити параметр
SQLDescribeParam Повернути опис маркера
параметра
SQLExecute Виконати запит
SQLExecDirect Виконати запит
безпосередньо
SQLNumParams Отримати число параметрів
в запитів
SQLNumResultCols Отримати число колонок в
результаті
SQLBindCol Зв'язати колонку із
змінною в програмі
SQLFetch Отримати наступний рядок
SQLGetDiagField Отримати діагностичні дані
для поля
SQLEndTran Закінчити транзакцію для
з'єднання
Вставка даних
Вибірка даних
Для вибірки даних з використанням запиту SELECT
необхідно зробити звязування змінних програми з
колонками результату і
покроково отримувати рядки даних.
(2) struct {
SQLINTEGER ind;
SQLCHAR value[20];
} firstname; /* variable to be bound to the
firstnme column */
struct {
SQLINTEGER ind;
SQLCHAR value[15];
} lastname; /* variable to be bound to the
lastname column */
struct {
SQLINTEGER ind;
SQLSMALLINT value;
} edlevel; /* variable to be bound to the edlevel
column */
Видалення даних
/* Perform Delete operation */
int DeleteEmployeeInfo(SQLHANDLE hdbc) {
int funcRc = 0;
SQLRETURN rc = SQL_SUCCESS;
SQLHANDLE hstmt; /* statement handle */
/* SQL DELETE statement to be executed */
(1) SQLCHAR *stmt = (SQLCHAR *)"DELETE FROM
employee
WHERE empno >= 50006";
Звільнення дескрипторів
Розробка прикладного
програмного забезпечення
для роботи з СУБД
на мові С#/.NET
DataSet
Це відєднане від СУБД представлення даних.
Представляє собою локальну копію відповідної частити
БД.
Дані можуть бути змінені незалежно від бази даних
Коли робота з DataSet завершена, зміни можуть бути
надіслані до СУБД для оновлення
Можна отримати для будь-якого джерела даних
(DataSource)
Data Provider
Відповідає за забезпечення та підтримку зєднання з
СУБД.
Являє собою набір компонентів, що забезпечують
ефективну роботу з даними
Кожен DataProvider складається з набору класів:
- Connection обєкт, що забезпечує зєднання з СУБД
- Command обєкт, що використовується для
виконання команд
- DataReader обєкт, що забезпечує forward-only та
read only зчитування даних
- DataAdapter - обєкт, що наповнює
відєднаний DataSet даними і
виконує оновлення
Connection
Connection використовується для зєднання з базою
даних.
Кожен data providers має свій власний
обєкт Connection Object
(DB2Connection, OleDbConnection,
і OdbcConnection).
connection.ConnectionString = Database=Sample;
Provid Приклад
er
DB2Connection connection =
IBM new DB2Connection(Database=SAMPLE);
Data
Server
Provide
r for
.NET
OLE DB
OleDbConnection connection =
.NET
new OleDbConnection(Provider=IBMDADB2;" +
Data "Data
Provide Source=sample;UID=userid;PWD=password;);
r
ODBC.
NET OdbcConnection connection = new
Data OdbcConnection("DSN=sample;UID=userid;PWD
Provide =password;");
r
Command
Provider Приклад
IBM Data Server
DB2Command cmd = new
Provider for .NET DB2Command();
OLE DB .NET
OleDbCommand cmd = new
Data Provider OleDbCommand();
ODBC.NET OdbcCommand cmd = new
Data Provider OdbcCommand();
Приклади:
cmd.CommandType = CommandType.Text;
cmd.CommandText = "SELECT manager FROM org WHERE
DEPTNUMB=10";
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = procName;
Методи обєкту Command
int count=(int)cmd.ExecuteScalar();
OLE DB .NET
OleDbDataAdapter adapter = new
Data Provider OleDbDataAdapter();
ODBC.NET OdbcDataAdapter adapter = new
Data Provider OdbcDataAdapter();
Клас DataReader
Клас DataReader застосовується для швидкого доступу
до записів в базі даних, отриманого в результаті
виконання SQL запиту чи вбудованої процедури.
Підтримує лише просування вперед по списку
результатів, і лише для читання.
Provider Приклад
IBM Data Db2DataReader reader =
Server cmd.ExecuteReader();
Provider for
.NET
Клас DataReader
Властивості
FieldCount повертає загальне число колонок для
поточного рядку
HasRows дозволяє чизначити чи є ще рядки для
читанням поверненням true або false.
int cols=reader.FieldCount;
bool rows=reader.HasRows;
Методи
Read зчитує один рядок і переміщає курсор до
наступного. Повертає true або false для позначення
того, чи є ще рядки для читання
bool done=reader.read();
Console.WriteLine (reader.GetString(1));
Методи DataSet:
AcceptChanges виконує коміт змін в DataSet
ds.AcceptChanges();
using System;
using System.Collections.Generic;
using System.Text;
using System.Data.OleDb;
namespace c2 {
class Program {
static void Main(string[] args) {
OleDbCommand cmd = null;
OleDbConnection con = null;
OleDbDataReader rdr = null;
int rowCount;
string v_IBMREQD, strMsg;
try {
con = new OleDbConnection
("DSN=sample;UID=db2admi
n;PWD=mypsw;" +
"Provider='IBMDADB2';");
cmd = new OleDbCommand();
cmd.Connection = con;
cmd.CommandText = "SELECT * FROM
SYSIBM.SYSDUMMY1";
cmd.CommandTimeout = 20;
con.Open();
rdr = cmd.ExecuteReader
(System.Data.Command
Behavior.SingleResult);
v_IBMREQD = "";
while (rdr.Read() == true) {
v_IBMREQD = rdr.GetString(0);
}
strMsg = " Successful retrieval of
record. Column" + "
'IBMREQD' has a
value of '" + v_IBMREQD
+ "'";
Console.WriteLine(strMsg);
Console.ReadLine();
rdr.Close();
con.Close();
} catch (OleDbException myException) {
}
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using System.Data.Odbc;
namespace c3 {
class Program {
static void Main(string[] args) {
OdbcCommand cmd = null;
OdbcConnection con = null;
OdbcDataReader rdr = null;
string v_IBMREQD, strMsg;
try {
con = new
OdbcConnection("DSN=sample;UID=db2admin
;PWD=mypsw;"
+ "Driver={IBM DB2 ODBC DRIVER};");
cmd = new OdbcCommand();
cmd.Connection = con;
cmd.CommandText = "SELECT * FROM
SYSIBM.SYSDUMMY1";
cmd.CommandTimeout = 20;
con.Open();
rdr = cmd.ExecuteReader
(System.Data.Command
Behavior.SingleResult);
v_IBMREQD = "";
Користувацька функція (UDF User Defined Function) дозволяє розширити SQL мови
та інкапсуляції бізнес-логіки.
Тригери бази даних об'єктів, що дозволяють адміністраторам баз даних автоматично перевірити прав
ильність даних перед їх вставкою чи зміною.
Вбудовані процедури
В DB2 збережені процедури можуть бути написані з використанням SQL PL SQL (процедурний мова), C
/ C + +, Java, COBOL, CLR (Common Language Runtime). У цьому
розділі ми зосередимося на SQL процедури PL через їх популярність, хорошу продуктивністю
і простоту. Мова SQL PL заснована на SQL / PSM стандарті.
У лівому верхньому кутку малюнка, ви побачите кілька SQL операторів, що виконуються один
за іншим. Кожен SQL передається від клієнта до
сервера даних, а сервер баз даних повертає результат клієнтові. Якщо виконуються багато SQL
запитів, це призводить до збільшення мережевого трафіку. З іншого боку, в нижній
частині альтернативний метод, який вимагає
менше мережевого трафіку. Другий метод викликає процедуру MyProc,
що зберігаються на сервері, яка містить ті ж SQL, а потім на стороні клієнта (на лівій стороні),
виклик оператор використовується для виклику збережених процедур. Другий спосіб
є більш ефективним, так як здійснюється тільки один запит до БД, що проходить через мережу, і
один результуючий набір повертається клієнтові.
Збережені процедури також можуть бути корисні в цілях безпеки в бази даних. Наприклад,
можна дозволити користувачам доступ до таблиць або представлень тільки через збережені
процедури, що допомагає блокувати роботу сервера і підтримувати доступ користувачів
до інформації, яку вони не повинні отримати. Це можливо тому, що користувачі не
вимагають явних привілеїв на таблиці або представлення, до
яких вони отримують доступ через збережені процедури, а їм просто повинні бути
надані достатні привілеї для виклику збережених процедур.
IBM Data Studio буде використовуватися в цьому розділі, для розробки збережених процедур,
призначених для користувача функцій і сервісів передачі даних мережі.
Рис.
2 Середовище IBM Data Studio
На рис. 4, переконайтеся, що у вікні Вибір поля бази даних вибрано DB2 для Linux, UNIX та Windows. У
пункті JDBC драйвер, за умовчанням після вибору DB2 для Linux, UNIX та Windows, буде
вибрано JDBC IBM Data Server JDBC Driver для SQLJ і JDBC (4.0). В поле хоста, ви можете ввести IP-
адресу або ім'я хоста (наприклад локальний). Переконатися, що з'єднання з
базою даних працює, можна натиснувши на кнопку Test Connection (в лівому нижньому кутку
рисунка). Якщо перевірка з'єднання пройшла успішно, натисніть кнопку Готово, і ім'я бази даних буде
додана в список з'єднань.
Далі вибравши базу даних, необхідно натиснути кнопку Готово і ваш проект зявиться у Project Explorer.
Після цього, натиснувши на символ "+", ви можете розгорнути проект, щоб побачити різні папки,
такі як PL / SQL пакети, SQL скрипти, збережені процедури і т.д.
Якщо ви хочете створити збережену процедуру, клацніть правою кнопкою миші на папці, збережених
процедур і виберіть New -> Stored Procedure.. Всю необхідну інформацію майстра Stored Procedure.,
такі як проект, що пов'язаний з процедурою, назва і
мова процедур і SQL заяви для використання в процедурі. За замовчуванням, Data Studio надає заяву
наприклад SQL. Прийміть всі значення за замовчуванням для всіх інших груп,
і в цей момент, ви можете натиснути Finish і збережена процедура створюється за
допомогою деякого коду шаблону і заяву SQL надані до якості прикладу. Це показано на рис. 5.
Коли процедура, була розгорнута, ви можете запустити її, клацнувши правою кнопкою на ній і
вибравши Run. Результати
будуть з'являтися на вкладці Result в нижньому правому кутку вікна Data Studio, як показано на рис. 7.
Для запуску процедури з вікна DB2 Command або командного редактор, ви можете використовувати
команду CALL <procedure name>. Але, перед цим необхідно підключитися до бази даних, де ця
процедура знаходиться.
Мова PL SQL
Структура процедур
CREATE PROCEDURE proc_name [( {optional parameters} )]
[optional procedure attributes]
<statement>
LANGUAGE SQL - цей атрибут задає мову, яки використовувати процедура. Мова SQL є значенням за
замовчуванням. Для інших мов, таких як Java або C необхідно використовувати Java і C відповідно.
RESULT SETS <n> - wе необхідно,
якщо збережена процедура буде повертатися n множин результату.
SPECIFIC my_unique_name - це унікальне ім'я, яке може бути задано процедурі.
Параметри
IN - вхідний параметр
OUT - вихідний параметр
INOUT - вхідний і вихідний параметр
Наприклад:
Для виклику
call P2 (3, 4, ?)
Складені оператори
Оголошення змінних
Присвоювання
Про, виникане помилка, якщо більше одного значення витягується з таблиці, і ви намагаєтеся
привласнити їй однієї змінної. Якщо вам потрібно зберігати більше інформації, ніж одне значення,
використовувати масиви або курсори.
Курсори
- CALLER: результуючий набір повертається клієнтові або збережена процедура, яка зрівнює
CREATE PROCEDURE set()
DYNAMIC RESULT SETS 1
LANGUAGE SQL
BEGIN
DECLARE cur CURSOR WITH RETURN TO CLIENT
FOR SELECT name, dept, job
FROM staff
WHERE salary > 20000;
OPEN cur;
END
Управління потоком
Як і в багатьох інших мовах, SQL PL має кілька контрукцій, які можуть бути використані для управління
потоком логіки:
- CASE (вибирає шляхи виконання, простий пошук)
- IF
- FOR (виконує тіло для кожного рядка таблиці)
- WHILE
- ITERATE (перехід до наступної ітерації. Як continue в C)
- LEAVE (вийти з блоку або циклу)
- LOOP (нескінченний цикл)
- REPEAT
Обробка помилок
В DB2 ключові слова SQLCODE і SQLSTATE використовуються для визначення успішного або
неуспішного виконання інструкції SQL. Ці ключові слова повинні бути явно оголошені в процедурі
наступним чином:
DECLARE SQLSTATE CHAR(5);
DECLARE SQLCODE INT;
DB2 встановить значення ключові слова автоматично після кожної операції SQL. Для SQLCODE
значення встановлюються таким чином:
- = 0, успішного.
- > 0, успішного з попередженням
- <0, невдало
- = 100, ніяких даних не було знайдено. (Тобто: FETCH повернув no data)
SQLCODE є СУБД конкретні і більш детальні, ніж SQLSTATE. SQLSTATE є стандартом серед СУБД, але
дуже загальний характер. Кілька SQLCODE, може відповідати одному SQLSTATE.
Обробники умов
Типи обробників
- CONTINUE - Цей обробник використовується для вказівки, що після того, як згенерується виняток і
обробник стану його обробить, потік виконання продовжить роботу з наступної інструкції після
інструкції, яка згенеревала виключення.
- EXIT - цей обробник використовується для вказівки на те, що після виключення і його обробник,
потік виконання переміститься в кінец процедури.
- Undo - Цей обробник використовується для вказівки, що після виникнення винятку і його обробки,
потік виконання переміститься кінця процедури, а всі попередньо виконані дії скасуються.
Наступні фрагменти коду показує, як для викликати збережені процедур з програм написаних
з використаннням CLI / ODBC і Java.
Dynamic SQL
У динамічних SQL, на відміну від статичного SQL, весь оператор SQL не відомо, під час виконання.
Наприклад, якщо col1 і tabname є змінними в цій заяві, то ми маємо справу з динамічним SQL:
Динамічний SQL рекомендується для DDL, щоб уникнути проблем з залежностями і пакет
недійсними. Також, необхідних для реалізації рекурсії.
Динамічний SQL може бути виконаний з використанням двох підходів:
- За допомогою директиви PREPARE разом із EXECUTE - це підходить для виконання декількох SQL
запитів
Фрагмент коду, показаний в лістингу, являє собою приклад динамічного SQL за допомогою двох
підходів. У прикладі передбачається, що таблиця T2 була створена з цим визначенням:
CREATE TABLE T2 (c1 INT, c2 INT)
Користувальницькі функції
Визначені користувачем функції (UDF) цє об'єкти баз даних, що перетворюють набір вхідних значень
даних в набір вихідних значень. Наприклад, функція може приймати значення величини в дюймах в
якості вхідних даних і повертати результат в сантиметрах.
DB2 підтримує створення функцій за допомогою SQL PL, PL/SQL, C/C++, Java, CLR
(Common Language Runtime) і OLE.
Скалярні функції
Скалярні функції повертають одне значення. Скалярні функції, не можуть включати в себе SQL запити,
які змінюють стан бази даних, тобто, INSERT, UPDATE і DELETE.
Деякими вбудованами скалярними функціями є SUM (), AVG (), DIGITS (), COALESCE () і SUBSTR ().
або
db2 "select (deptname ('000300')) from sysibm.sysdummy1"
Функції таблиці
Табличні функції схожі на представлення (VIEW), але оскільки вони допускають використання
інструкцій зміни даних (INSERT, UPDATE і DELETE), вони є більш потужними. Як правило, вони
використовуються для збереження аудиторських даних.
CREATE FUNCTION getEnumEmployee(p_dept VARCHAR(3))
RETURNS TABLE
(empno CHAR(6),
lastname VARCHAR(15),
firstnme VARCHAR(12))
SPECIFIC getEnumEmployee
RETURN
SELECT e.empno, e.lastname, e.firstnme
FROM employee e
WHERE e.workdept=p_dept
Тригери
The big picture
Тригери
Event-Condition-Action Rules
Тригери
Створення тригера
[ referencing-
variables ] insert new data
- Old Row As delete old data
- New Row As update old/new data
- Old Table
- New Table
Приклад тригера
Referential Integrity:
R.A посилається на S.B, реалізація каскадного
видалення (cascaded delete)
Before triggers
After triggers
After тригери активуються після виконання
дій SQL запиту і до його успішного завершення.
Instead of triggers
Приклад представлення
СREATE VIEW EMPV(EMPNO, FIRSTNME, MIDINIT,
LASTNAME, PHONENO,
HIREDATE, DEPTNAME)
AS SELECT EMPNO, FIRSTNME, MIDINIT, LASTNAME,
PHONENO,
HIREDATE, DEPTNAME
FROM EMPLOYEE, DEPARTMENT
WHERE EMPLOYEE.WORKDEPT = DEPARTMENT.DEPTNO
Операція INSERT
CREATE TRIGGER EMPV_INSERT INSTEAD OF INSERT ON EM
PV
REFERENCING NEW AS NEWEMP FOR EACH ROW
INSERT INTO EMPLOYEE (EMPNO, FIRSTNME, MIDINIT,
LASTNAME,
WORKDEPT, PHONENO, HIREDATE)
VALUES(EMPNO, FIRSTNME, MIDINIT, LASTNAME,
COALESCE(
(SELECT DEPTNO FROM DEPARTMENT AS D
WHERE D.DEPTNAME = NEWEMP.DEPTNAME),
RAISE_ERROR('70001', 'Unknown dept name')),
PHONENO, HIREDATE)
Операція DELETE
CREATE TRIGGER EMPV_DELETE INSTEAD OF DELETE ON EM
PV
REFERENCING OLD AS OLDEMP FOR EACH ROW
DELETE FROM EMPLOYEE AS E WHERE E.EMPNO =
OLDEMP.EMPNO
Операція UPDATE
CREATE TRIGGER EMPV_UPDATE INSTEAD
OF UPDATE ON EMPV
REFERENCING NEW AS NEWEMP OLD AS OLDEMP FOR EACH
ROW
BEGIN ATOMIC
VALUES(CASE WHEN NEWEMP.EMPNO = OLDEMP.EMPNO THEN
0
ELSE RAISE_ERROR('70002', 'Must not change
EMPNO') END);
UPDATE EMPLOYEE AS E
SET (FIRSTNME, MIDINIT, LASTNAME, WORKDEPT,
PHONENO, HIREDATE)
= (NEWEMP.FIRSTNME, NEWEMP.MIDINIT,
NEWEMP.LASTNAME, COALESCE(
(SELECT DEPTNO FROM DEPARTMENT AS D
WHERE D.DEPTNAME = NEWEMP.DEPTNAME),
RAISE_ERROR ('70001', 'Unknown dept name')),
NEWEMP.PHONENO, NEWEMP.HIREDATE)
WHERE NEWEMP.EMPNO = E.EMPNO;
END
Приклади
Завдання:
Нові студенти з GPA > 4 автоматично записуються на напрям
прогрaмна інженерія та компютерні науки в ТНТУ
CREATE TRIGGER R1
AFTER INSERT ON STUDENT
FOR EACH ROW
WHEN NEW.GPA > 4
BEGIN
INSERT INTO APPLY VALUES (NEW.SID, TNTU, 'SE',
NULL);
INSERT INTO APPLY VALUES (NEW.SID, 'TNTU', 'CS',
NULL);
END;
Приклади
Завдання:
Каскадне видалення з таблиці заявок (apply) при видаленні
студента
CREATE TRIGGER R2
AFTER DELETE ON STUDENT
FOR EACH ROW
BEGIN
DELETE FROM APPLY WHERE SID = OLD.SID;
END;
Приклади
Завдання:
Каскадне оновлення назви вузу в таблиці заявок(apply) при її
зміні в таблиці вузів (univ)
CREATE TRIGGER R3
AFTER UPDATE OF UNAME ON UNIV
FOR EACH ROW
BEGIN
UPDATE APPLY
SET UNAME = NEW.UNAME
WHERE UNAME = OLD.CNAME;
END;
Приклади
Завдання:
Перевірка унікальності назви університету (uname)
CREATE TRIGGER R4
BEFORE INSERT ON UNIV
FOR EACH ROW
WHEN EXISTS (SELECT * FROM UNIV WHERE UNAME =
NEW.UNAME)
BEGIN
SELECT RAISE(IGNORE);
END;
Приклади
Завдання:
Коли кількість заявок у вуз перевищує 100, позначити його як
заповнений (додати до назви done)
CREATE TRIGGER R6
AFTER INSERT ON APPLY
FOR EACH ROW
WHEN (SELECT COUNT(*) FROM APPLY WHERE CNAME =
NEW.CNAME) > 100
BEGIN
UPDATE UNIV SET UNAME = UNAME || '-DONE'
WHERE UNAME = NEW.UNAME;
END;
Приклади
Завдання:
При зменшенні обсягу замовлення для університету із > 1000
до < 1000, видалити усій заявки на спеціальність
зварювання (ZV) і змінити рішення (DECISION) для вже
прийнятих (Y)студентів на невизначене (U)
Обєктно-реляційний
мапінг
(ORM)
Що таке ORM
ORM або Object - relational mapping (Об'єктно-
реляційне відображення ) - це технологія програмування
, яка дозволяє перетворювати несумісні типи моделей в
ООП , зокрема , між сховищем даних і об'єктами
програмування.
4. Функції оптимізації.
Java C#
- Enterprise JavaBeans - ADO.NET Entity Framework,
Entity Beans
- Business Logic Toolkit
- Java Data Objects - DataObjects.NET,
- Castor
- iBATIS,
- TopLink
- LINQ to SQL,
- Spring DAO
- Persistor.NET
- OpenJPA
- NHibernate,
- Hibernate
C++ PHP
- LiteSQL - CakePHP
- ODB - Doctrine,
- Wt::Dbo - Redbean
- QxOrm - Torpor,
- Yii,
- Zend Framework,
Source: http://en.wikipedia.org/wiki/List_of_object-relational_mapping_software
Hibernate
Підтримувані СУБД
DB2 org.hibernate.dialect.DB2Dialect
HSQLDB org.hibernate.dialect.HSQLDialect
HypersonicSQL org.hibernate.dialect.HSQLDialect
Informix org.hibernate.dialect.InformixDialect
Ingres org.hibernate.dialect.IngresDialect
Interbase org.hibernate.dialect.InterbaseDialect
MySQL org.hibernate.dialect.MySQLDialect
Oracle (any version) org.hibernate.dialect.OracleDialect
Oracle 9i org.hibernate.dialect.Oracle9iDialect
PostgreSQL org.hibernate.dialect.PostgreSQLDialect
Progress org.hibernate.dialect.ProgressDialect
SAP DB org.hibernate.dialect.SAPDBDialect
Sybase org.hibernate.dialect.SybaseDialect
hibernate.cfg.xml
<?xml version="1.0" encoding="utf-8"
<!DOCTYPE hibernate-configuration SYSTEM
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.dialect">
org.hibernate.dialect.MySQLDialect
</property>
<property name="hibernate.connection.driver_class">
com.mysql.jdbc.Driver
</property>
</session-factory>
</hibernate-configuration>
public Employee() {}
public Employee(String fname, String lname, int salary) {
this.firstName = fname;
this.lastName = lname;
this.salary = salary;
}
public int getId() {
return id;
}
public void setId( int id ) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName( String first_name ) {
this.firstName = first_name;
}
public void setLastName( String last_name ) {
this.lastName = last_name;
}
public int getSalary() {
return salary;
}
public void setSalary( int salary ) {
this.salary = salary;
}
Файл employee.hbm.xml
<?xml version="1.0" encoding="utf-8"
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="Employee" table="EMPLOYEE">
<meta attribute="class-description">
This class contains the employee detail.
</meta>
<id name="id" type="int" column="id">
<generator class="native"/>
</id>
<property name="firstName" column="first_name" type="string"/>
<property name="lastName" column="last_name" type="string"/>
<property name="salary" column="salary" type="int"/>
</class>
</hibernate-mapping>
@Entity
@Table(name = "EMPLOYEE")
public class Employee {
@Id @GeneratedValue
@Column(name = "id")
private int id;
@Column(name = "first_name")
private String firstName;
@Column(name = "last_name")
private String lastName;
@Column(name = "salary")
private int salary;
public Employee() {}
public int getId() {
return id;
}
public void setId( int id ) {
this.id = id;
}
public String getFirstName() {
return firstName;
...
execute dbms_stats.gather_index_stats(ownname=>'stud',
indname=>'i', partname=>null, estimate_percent=>50, stattab=>null, statid=>null,
statown=>null);
execute dbms_stats.gather_table_stats(ownname=>'stud',
tabname=>'t', partname=>null, estimate_percent=>50, block_sample=>false,
method_opt=>'FOR ALL COLUMNS', degree=>null,
cascade=>true, stattab=>null, statid=>null, statown=>null);
execute dbms_stats.gather_table_stats(ownname=>'stud',
tabname=>'t', partname=>null, estimate_percent=>50, block_sample=>false,
method_opt=>'FOR COLUMNS object_name, object_id',
degree=>null, cascade=>true, stattab=>null,
statid=>null, statown=>null);
execute dbms_stats.gather_schema_stats(ownname=>'stud',
estimate_percent=>50, block_sample=>false, method_opt=>'FOR ALL COLUMNS',
degree=>null, cascade=>true, stattab=>null, statid=>null, statown=>null);
execute dbms_stats.delete_index_stats(ownname=>'stud',
indname=>'i', partname=>null, stattab=>null, statid=>null, statown=>null);
execute dbms_stats.delete_table_stats(ownname=>'stud',
tabname=>'t', partname=>null, stattab=>null, statid=>null,
statown=>null, cascade_parts=>true, cascade_columns=>true);
Статистика по таблицях
Статистика по індексах
Статистика по стовпцях
-- створення обєктів
drop table h;
Класичні індекси
Індекси на основі В*-дарева найбільш широко використовуваний тип індексної структури в
базі даних. По реалізації вони подібні бінарному дереву пошуку. Мета їх створення
мінімізувати час пошуку даних сервером Oracle. При наявності індексу по числовому
стовпцю, структура індексу може виглядати так:
Блоки самого нижчого рівня в індексі, які називають листовими вершинами, містять всі
проіндексовані ключі і ідентифікатори рядків (rid на схемі), що посилаються на відповідні
рядки. Проміжні блоки над листовими вершинами називають блоками розгалуження. Вони
використовуються для переходу по структурі. Наприклад, якщо необхідно знайти в індексі
значення 42, потрібно почати з вершини дерева і рухатись вправо. При перевірці цього
блоку виявляється, що необхідно перейти до блоку в діапазоні "от 40 до 50". Цей блок
виявляється листовим і посилається на рядки, які містять число 42. Цікаво відмітити, що
листові блоки фактично утворюють двохзвязний список. Як тільки знайдено "початок" серед
листових вершин, тобто перше значення, дуже легко переглядати значення по порядку (це
називають також переглядом діапазону по індексу, index range scan). Проходити по
структурі індексу більше не потрібно; ми просто переходим по листових вершинах. Це
суттєво спрощує пошук рядків по умовах слідуючого типу:
-- індекси
-- структура індексу, rowid
truncate table h;
insert into h select rownum, object_name,
object_id, object_id from all_objects where rownum < 10;
commit;
declare
r_t number;
o_n number;
f_n number;
b_n number;
r_n number;
r rowid;
begin
select rowid into r from h where rownum < 2;
-- створення індексів
truncate table h;
commit;
analyze table h compute statistics for table for all indexes for all indexed col
umns;
set autotrace on
set timing on
-- операции по индексу
drop index ind_s on h(s);
select * from h where s = 'aaaa';
analyze table h compute statistics for table for all indexes for all indexed col
umns;
delete from h;
analyze table h compute statistics for table for all indexes for all indexed col
umns;
Функціональні індекси
Індекси по функції. Ці індекси на основі В*-дерева або бітових карт зберігають вирахуваний
результат застосування функції до стовпця або стовпцям рядка, а не самі дані рядка. Це
можна використовувати для прискорення виконання запиту виду:
-- функціональні індекси
select * from h where n*n = 100;
Бітові індекси
Зазвичай в В*-дереві є однозначна відповідність між записом індексом і рядком - запис
індексу вказує на рядок. В індексі на основі бітових карт запис використовує бітову карту
для посилання на більшу кількість рядків одночасно. Такі індекси підходять для даних з
невеликою кількістю різних значень, які звичайно тільки читаються. Стовпець, який має
всього три значення Y, N і NULL, в таблиці з мільйоном рядків дуже добре підходить для
створення індексу на основі бітових карт. Припустимо, створюється індекс на основі бітових
карт по стовпцю JOB в таблиці ЕМР:
-- bitmap індекси
drop table bt;
analyze table bt compute statistics for table for all indexes for all indexed co
lumns;
Індекс-організовані таблиці
Індекс-організовані таблиці - кластерні індекси, в індексі зберігаються значення стовпців,
вибраних для індексу, зєднанні в одне значення. Індекс-організовані таблиці мають
фіктивний rowid - значення індексу. При запиті здійснюється швидке сканування індексів.
Використовування кластерних індексів здаьне помітно збільшити продуктивність пошуку
даних навіть по порівнянню з некластерними індексами, особливо при роботі з
послідовностями даних. В якості кластерного індексу слід вибирати стовпці, що найбільш
часто задаються в якості критеріїв пошуку. При цьому не слід викорисовувати для
індексування дуже довгі стовпці. Кластерний індекс може включати кілька стовпців, але
кількість стовпців кластерного індексу слід по можливості звести до мінімуму. Слід уникати
створення кластерного індексу для часто змінюваних стовпців, так як сервер повинен буде
виконувати фізичне переміщення всіх даних в таблиці, щоб вони знаходились в
упорядкованому стані, як того потребує кластерний індекс. Для інтенсивно змінюваних
стовпців більше підходить не кластерний індекс .
індекс-організовані таблиці
create table ih(p number constraint ipk primary key, s varchar2(100) null, n num
ber null, nu number null constraint iun unique)
organization index;
analyze table ih compute statistics for table for all indexes for all indexed co
lumns;
commit;
Матеріалізовані уявлення
Як відомо, уявлення (view) це запит на вибірку, який зберігається на сервері, як окремий
обєкт. Так як, результат цього запиту можна розглядати в якості таблиці, уявлення
допускається використовувати в інших запитах, також як любу звичайну таблицю.
Матеріалізоване уявлення зберігається на сервері у вигляді таблиці, яка автоматично
оновляється при зміні даних, які мають відношення до цього уявлення. При виконанні
запиту, основаного на матеріалізованому уявленні, використовуються не вихідні таблиці і
запит, на якому базується уявлення, а дані, які зберігаються в цьому уявленні. За рахунок
цього швидкість виконання запитів може бути підвищена на порядки. Основним недоліком
матеріалізованого уявлення являється те, що для його використання потрібно додатковий
дисковий простір і його необхідно синхронізувати з основними даними.
Створення обєктів
create table h1(n number primary key, s varchar2(100) null, n1 number null, s1 v
archar2(100));
create table h2(n number primary key, s varchar2(100) null, n1 number null, s1 v
archar2(100));
insert into h1(n, s, n1, s1) select object_id, object_name, object_id, owner fro
m all_objects;
insert into h2(n, s, n1, s1) select object_id, object_name, object_id, owner fro
m all_objects;
analyze table h1 compute statistics for table for all columns for all indexes;
analyze table h2 compute statistics for table for all columns for all indexes;
create view v1 as select h1.n, h1.s, h2.s1, h2.n1 from h1 inner join h2 on h1.n =
h2.n and h1.s = h2.s;
create materialized view v2 as select h1.n, h1.s, h2.s1, h2.n1 from h1 inner joi
n h2 on h1.n = h2.n and h1.s = h2.s;
Способи побудови
Існує два способи формування уявлення - безпосередньо при його створенні або
відкладене, по явній команді.
exec dbms_mview.refresh('V3');
Частота оновлення
commit;
commit;
create materialized view v3 build immediate refresh complete start with '17-MAY-
2004' next sysdate+1 as select h1.s1 s1, count(h1.n1) n1 from h1 group by s1 hav
ing count(*) > 1;
@?/rdbms/admin/utlxmv.sql
Спосіб оновлення
Існує два основних способи оновлення матеріалізованих уявлень
Повна перебудова. В цьому випадку при кожному оновленні даних відбувається
виконання запиту, на основі якого побудовано уявлення і дані повністю
перегружаються.
Часткове оновлення. Для кожної таблиці яка бере участь в запиті на уявлення,
створюється журнал змін і зміни подання виконуються тільки даних, измененных
змінених в основних таблицях.
drop materialized view v3;
create materialized view v3 build immediate refresh complete as select h1.s1 s1
, count(h1.n1) n1 from h1 group by s1 having count(*) > 1;
commit;
exec dbms_mview.refresh('v3');
create materialized view log on h1 nologging with sequence, rowid (n1, s1) incl
uding new values;
create materialized view log on h2 nologging with sequence, rowid (n1, s1) incl
uding new values;
create materialized view v3 refresh fast on commit as select h1.s1 s1, count(h1
.n1) n1 from h1 group by s1;
commit;
create materialized view log on h1 nologging with sequence, rowid (n, n1, s1) i
ncluding new values;
create materialized view log on h2 nologging with sequence, rowid (n, n1, s1) i
ncluding new values;
create materialized view v3 refresh fast as select h1.s1 s1, h2.s1 s2, h1.n n f
rom h1, h2 where h1.n = h2.n;
create materialized view v3 refresh fast as select h1.rowid h1_rowid, h2.rowid h
2_rowid, h1.s1 s1, h2.s1 s2, h1.n n from h1, h2 where h1.n = h2.n;
create materialized view v3 refresh fast on commit as select h1.s1 s1, h2.s1 s2
, h1.n n from h1, h2 where h1.n = h2.n;
create materialized view v3 refresh fast on commit as select h1.rowid h1_rowid,
h2.rowid h2_rowid, h1.s1 s1, h2.s1 s2, h1.n n from h1, h2 where h1.n = h2.n;