SUBD Labs 8-13
.pdfХід роботи.
Напишемо функції, які будуть обгортками стандартних функцій шифрування, та процедуру, яка буде обчислювати кількість написаних автором повідомлень у кожній категорії за вказаний проміжок часу.
1. Функції шифрування/дешифрування із заданим ключем.
CREATE FUNCTION mycms_encode (pass CHAR(48))
RETURNS TINYBLOB
RETURN AES_ENCRYPT(pass, 'key-key');
CREATE FUNCTION mycms_decode (pass TINYBLOB)
RETURNS CHAR(48)
RETURN AES_DECRYPT(pass, 'key-key');
2. Процедура повинна рахувати кількість повідомлень автора написаних за певний проміжок часу у кожній з існуючих категорій. Для цього потрібно відібрати всі повідомлення та їх категорії за автором та часом написання. Потім згрупувати вибрані повідомлення за категоріями та порахувати кількість повідомлень. У процедуру потрібно передати ім’я автора, а також першу і другу дату.
Перед основними директивами додамо перевірку коректності задання початкової і кінцевої дати (IF date1<=date2 THEN…). Результати обчислень будуть записуватись у таблицю Stats, яку процедура завжди очищує (командою TRUNCATE mycms.stats) і заповнює з нуля.
DELIMITER //
CREATE PROCEDURE mycms_count (IN name CHAR(19), IN date1 DATE, IN date2 DATE)
BEGIN
DECLARE error CHAR;
SET error = 'Некоректно задані дати';
IF (date1<=date2) THEN
BEGIN
CREATE TABLE IF NOT EXISTS mycms.stats (category CHAR(20), amount INT UNSIGNED);
TRUNCATE mycms.stats;
INSERT INTO mycms.stats SELECT cname AS category, COUNT(message.messageID) AS amount
FROM ((author INNER JOIN message)
INNER JOIN message_category) INNER JOIN category ON author.login=name
AND author.authorID=message.authorID
AND message.messageID=message_category.messageID AND message_category.categoryID=category.categoryID WHERE message.posted BETWEEN date1 AND date2
GROUP BY category;
END;
ELSE SELECT error;
END IF;
END//
DELIMITER ;
3. Після створення функцій і процедури перевіримо їх роботу:
SELECT login, mycms_decode(password) FROM author LIMIT 4;
CALL mycms_count('user1', '2008-01-01', '2009-05-05');
SELECT * FROM stats;
Результат роботи процедури – таблиця stats:
CALL mycms_count('user1', '2010-01-01', '2009-05-05');
Результат виклику процедури:
Висновок: на цій лабораторній роботі я навчився розробляти та використовувати збережені процедури і функції у СУБД MySQL.
Лабораторна робота №11
з курсу “СУБД” на тему:
“Розробка та застосування транзакцій”
Мета роботи: Навчитися використовувати механізм транзакцій у СУБД MySQL. Розробити SQL запити, які виконуються як єдине ціле в рамках однієї транзакції.
Короткі теоретичні відомості.
Транзакція – це сукупність директив SQL, які виконуються як єдине ціле з можливістю відміни результатів їх виконання. Зміни в таблицях записуються у базу даних лише після успішного виконання всіх директив транзакції. Інакше, всі зроблені зміни ігноруються. Це дозволяє уникати помилок при маніпулюванні великими обсягами записів, зберігати цілісність даних при помилках під час додавання, видалення, модифікації значень у різних таблицях і полях тощо. СУБД MySQL також підтримує глобальні розподілені транзакції, які виконуються на декількох базах даних, або на різних серверах баз даних (ХА-транзакції).
Для організації транзакцій в MySQL використовують такі директиви, як SET autocommit, START TRANSACTION, COMMIT і ROLLBACK.
START TRANSACTION
Вказує на початок транзакції. Директива вимикає автоматичне збереження змін для всіх подальших запитів, поки не буде виконано команду COMMIT, або ROLLBACK.
COMMIT
Зберегти зміни, зроблені даною транзакцією.
ROLLBACK
Відмінити дану транзакцію і зроблені нею зміни у базі даних. Слід зауважити, що зміни у схемі бази даних не можна відмінити, тобто результат видалення, зміни або створення таблиці завжди зберігається.
SET autocommit=0
Вимикає автоматичне збереження змін для поточної сесії зв’язку з сервером БД. За замовчуванням, зміни зберігаються автоматично, тобто результат виконання запиту, який змінює таблицю, одразу записується на диск без можливості відміни операції.
AND CHAIN
Одразу після завершення даної транзакції розпочати виконання наступної.
RELEASE
Одразу після виконання даної транзакції завершити поточну сесію зв’язку з сервером.
Транзакції можна розбивати на окремі логічні частини, оголошуючи так звані точки збереження. Це дозволяє відміняти результати виконання не всієї транзакції, а лише тих запитів, які виконувались після оголошеної точки збереження (SAVEPOINT).
SAVEPOINT мітка
Оголошує точку збереження всередині транзакції та задає її назву.
ROLLBACK TO [SAVEPOINT] мітка
Відміняє результати виконання запитів, вказаних після даної точки збереження.
RELEASE SAVEPOINT мітка
Видаляє точку збереження.
Хід роботи.
В ході роботи, потрібно продемонструвати успішне і неуспішне виконання транзакції. Розробимо транзакцію, яка буде вносити дані в таблицю Author i Role. Транзакція буде
відміняти всі зміни у таблицях при виникненні помилки чи іншої суперечливості.
1. Відміна транзакції.
Транзакція складається з чотирьох запитів на додавання нових користувачів у групу "ugroup" та "sugroup3". При цьому, групи "sugroup3" з roleID=9 в базі даних не існує, а отже, транзакція не виконується.
START TRANSACTION;
INSERT INTO mycms.author VALUE (NULL, NULL, 'user7', 'u7pass', '2008-04-16', 'user7@kml.com', NULL, 2);
INSERT INTO mycms.author VALUE (NULL, NULL, 'user8', 'u8pass', '2009-04-22', 'user8@kml.com', NULL, 2);
INSERT INTO mycms.author VALUE (NULL,NULL, 'superuser4', 'suser4_pass', '2009-05-01', 'suser4@gl.com', NULL, 9); INSERT INTO mycms.author VALUE (NULL,NULL, 'suser5', 'suuser5_pass', '2009-05-01', 'suser5@gl.com', NULL, 9);
COMMIT;
Відповідь сервера:
#1452 - Cannot add or update a child row: a foreign key constraint fails (`mycms/author`, CONSTRAINT `author_role` FOREIGN KEY (`roleID`) REFERENCES `role` (`roleID`) ON DELETE NO ACTION ON UPDATE NO ACTION)
2. Успішна транзакція.
Транзакція складається з запитів на додавання тих самих користувачів у групу "ugroup" та "sugroup3" після створення у таблиці Role групи "sugroup3".
INSERT INTO role
VALUE (NULL,'SUGroup3', 'read, write, changeown, groupadmin');
START TRANSACTION;
INSERT INTO mycms.author VALUE (NULL, NULL, 'user7', 'u7pass', '2008-04-16', 'user7@kml.com', NULL, 2);
INSERT INTO mycms.author VALUE (NULL, NULL, 'user8', 'u8pass', '2009-04-22', 'user8@ml.com', NULL, 2);
INSERT INTO mycms.author VALUE (NULL,NULL, 'superuser4', 'suser4_pass', '2009-05-01', 'suser4@gl.com', NULL, 9); INSERT INTO mycms.author VALUE (NULL,NULL, 'suser5', 'suuser5_pass', '2009-05-01', 'suser5@gl.com', NULL, 9);
COMMIT;
Результат успішного додавання чотирьох користувачів у таблицю показано нижче:
SELECT * FROM author LIMIT 9, 5;
Висновок: На цій лабораторній роботі я ознайомився із механізмом транзакцій у СУБД
MySQL.
Лабораторна робота №12
з курсу “СУБД” на тему:
“Розробка та застосування тригерів”
Мета роботи: Розробити SQL запити, які моделюють роботу тригерів: каскадне знищення, зміна та доповнення записів у зв’язаних таблицях.
Короткі теоретичні відомості.
Тригер – це спеціальний вид користувацької процедури, який виконується автоматично при певних діях над таблицею, наприклад, при додаванні чи оновленні даних. Кожен тригер асоційований з конкретною таблицею і подією. Найчастіше тригери використовуються для перевірки коректності вводу нових даних та підтримки складних обмежень цілісності. Крім цього їх використовують для автоматичного обчислення значень полів таблиць, організації перевірок для захисту даних, збирання статистики доступу до таблиць баз даних чи реєстрації інших подій.
Для створення тригерів використовують директиву CREATE TRIGGER.
Синтаксис:
CREATE
[DEFINER = { користувач | CURRENT_USER }]
TRIGGER ім’я_тригера час_виконання подія_виконання ON назва_таблиці FOR EACH ROW тіло_тригера
Аргументи:
DEFINER
Задає автора процедури чи функції. За замовчуванням – це CURRENT_USER.
ім’я_тригера
Ім’я тригера повинно бути унікальним в межах однієї бази даних.
час_виконання
Час виконання тригера відносно події виконання. BEFORE – виконати тіло тригера до виконання події, AFTER – виконати тіло тригера після події.
подія_виконання
Можлива подія – це внесення (INSERT), оновлення (UPDATE), або видалення (DELETE) рядка з таблиці. Один тригер може бути пов’язаний лише з однією подією. Команда AFTER INSERT, AFTER UPDATE, AFTER DELETE визначає виконання тіла тригера відповідно після внесення, оновлення, або видалення даних з таблиці. Команда
BEFORE INSERT, BEFORE UPDATE, BEFORE DELETE визначає виконання тіла тригера відповідно до внесення, оновлення, або видалення даних з таблиці.
ON назва_таблиці
Таблиця, або віртуальна таблиця (VIEW), для якої створюється даний тригер. При видалені таблиці з бази даних, автоматично видаляються всі пов’язані з нею тригери.
FOR EACH ROW тіло_тригера
Задає набір SQL директив, які виконує тригер. Тригер викликається і виконується для кожного зміненого рядка. Директиви можуть об’єднуватись командами BEGIN … END та містити спеціальні команди OLD та NEW для доступу до попереднього та нового значення поля у зміненому рядку відповідно. В тілі тригера дозволено викликати збережені процедури, але заборонено використовувати транзакції, оскільки тіло тригера автоматично виконується як одна транзакція.
NEW.назва_поля
Повертає нове значення поля для зміненого рядка. Працює лише при подіях INSERT та UPDATE. У тригерах, які виконуються перед (BEFORE) подією можна змінити нове значення поля командою SET NEW.назва_поля = значення.
OLD.назва_поля
Повертає старе значення поля для зміненого рядка. Можна використовувати лише при подіях UPDATE та DELETE. Змінити старе значення поля не можливо.
Щоб видалити створений тригер з бази даних, потрібно виконати команду
DROP TRIGGER назва_тригера.
Хід роботи.
Потрібно розробити тригери, які виконуватимуть наступні дії.
1.Каскадне оновлення таблиці користувачів при видаленні ролі з таблиці Role.
2.Шифрування паролю користувача під час внесення в таблицю.
3.Тригер для таблиці Session, який буде фіксувати у таблиці Author дату останнього входу користувача в систему.
1. Каскадне оновлення таблиці користувачів при видаленні ролі з таблиці Role. Діюче обмеження зовнішнього ключа при видалені ролі встановлює для користувача невизначену роль (значення NULL). Натомість, за допомогою тригера, користувачеві потрібно присвоювати певну роль за замовчуванням (роль Guests з roleID=4).
CREATE
TRIGGER role_delete BEFORE DELETE ON mycms.role FOR EACH ROW
UPDATE mycms.author SET roleID=4 WHERE roleID=OLD.roleID;
Перевіримо роботу тригера, видаливши роль з номером 9:
DELETE FROM mycms.role WHERE roleID=9;
SELECT * FROM mycms.author LIMIT 10, 5;
2. Створимо тригер, який буде шифрувати пароль користувача функцією AES_ENCRYPT перед тим як внести його у таблицю Author.
CREATE
TRIGGER author_password BEFORE INSERT ON mycms.author FOR EACH ROW
SET NEW.password = AES_ENCRYPT(NEW.password, 'key-key');
Перевіримо виконання тригера:
INSERT INTO mycms.author VALUES
(NULL, NULL, 'superuser6', 'suser6_pass', '2009-05-09', 'suser6@g.com', NULL, 6),
(NULL, NULL, 'superser7', 'suser7_pass', '2009-05-09', 'suser7@g.com', NULL, 6);
SELECT * FROM mycms.author LIMIT 14, 2;
3. У таблицю Session за допомогою тригера потрібно записувати службову інформацію при кожному вході користувача у систему. Тригер буде фіксувати дату входу і записувати її у таблицю користувачів.
Перед створенням тригера, створимо нове поле lastseen у таблиці Author.
ALTER TABLE mycms.author
ADD COLUMN lastseen DATE DEFAULT NULL;
CREATE TRIGGER user_lastseen AFTER INSERT ON mycms.session FOR EACH ROW
UPDATE mycms.author SET author.lastseen=DATE(NEW.start) WHERE author.authorID=NEW.authorID;
Перевіримо роботу тригера:
INSERT INTO session VALUES
('2weQ34rt', '3', '2009-05-09 00:01:01', NULL), ('314eqrtE', '4', '2009-05-10 22:01:51', NULL);
SELECT authorID, login, email, lastseen FROM author LIMIT 3;
Висновок: на цій лабораторній роботі було розглянуто тригери, їх призначення, створення та використання. Було розроблено тригери для таблиць Session, Role та Author.
Лабораторна робота №13
з курсу “СУБД” на тему:
“Аналіз та оптимізація запитів”
Мета роботи: Навчитися аналізувати роботу СУБД та оптимізовувати виконання складних запитів на вибірку даних. Виконати аналіз складних запитів за допомогою директиви EXPLAIN, модифікувати найповільніші запити з метою їх пришвидчення.
Короткі теоретичні відомості.
Для аналізу виконання запитів в MySQL існує декілька спеціальних директив. Основна з них – EXPLAIN.
Директива EXPLAIN дозволяє визначити поля таблиці, для яких варто створити додаткові індекси, щоб пришвидшити вибірку даних. Індекс – це механізм, який підвищує швидкість пошуку та доступу до записів за індексованими полями. Загалом, варто створювати індекси для тих полів, за якими відбувається з’єднання таблиць, перевірка умови чи пошук.
За допомогою директиви EXPLAIN також можна визначити послідовність, в якій відбувається з’єднання таблиць при вибірці даних. Якщо оптимізатор вибирає не найкращу послідовність з’єднання таблиць, потрібно використати опцію STRAIGHT_JOIN директиви SELECT. Тоді з’єднання таблиць буде відбуватись в тому порядку, в якому перераховані таблиці у запиті. Також, за допомогою опцій FORCE INDEX, USE INDEX та IGNORE INDEX можна керувати використанням індексів у випадку їх неправильного вибору оптимізатором, тобто, якщо вони не підвищують ефективність вибірки рядків.
Опис директив.
SELECT BENCHMARK(кількість_циклів, вираз)
Виконує вираз вказану кількість разів, і повертає загальний час виконання.
EXPLAIN SELECT …
Використовується разом із запитом SELECT. Виводить інформацію про план обробки і виконання запиту, включно з інформацією про те, як і в якому порядку з’єднувались таблиці. EXPLAIN EXTENDED виводить розширену інформацію.
Результати директиви виводяться у вигляді рядків з такими полями:
id – порядковий номер директиви SELECT у запиті;
select_type – тип вибірки (simple, primary, union, subquery, derived, uncachable subquery тощо);
table – назва таблиці, для якої виводиться інформація;
type – тип з’єднання (system, const, eq_ref, ref, fulltext, range тощо); possible_keys – індекси, які наявні у таблиці, і можуть бути використані; key – назва індексу, який було обрано для виконання запиту;
key_len – довжина індекса, який був використаний при виконанні запиту;
ref – вказує, які рядки чи константи порівнюються зі значенням індекса при відборі; rows – (прогнозована) кількість рядків, потрібних для виконання запиту;
Extra – додаткові дані про хід виконання запиту.
ANALYZE TABLE
Оновлює статистичну інформацію про таблицю (наприклад, поточний розмір ключових полів). Ця інформація впливає на роботу оптимізатора запитів, і може вплинути на вибір індексів при виконанні запитів.
SHOW INDEX FROM ім’я_таблиці
Виводить інформацію про індекси таблиці.
CREATE [UNIQUE | FULLTEXT] INDEX назва
ON ім’я_таблиці (перелік_полів)
Створює індекс для одного або декількох полів таблиці. Одне поле може входити до кількох індексів. Якщо індекс оголошено як UNIQUE, то значення відповідних полів таблиці повинні бути унікальними. Таблиці MyISAM підтримують створення повнотекстових індексів (FULLTEXT) для полів типу TEXT, CHAR, VARCHAR.
Завдання на лабораторну роботу.
1.Визначити індекси таблиці.
2.Створити додаткові індекси для таблиці.
3.Дослідити процес виконання запитів за допомогою EXPLAIN.
Хід роботи.
1. За допомогою директиви SHOW INDEX визначимо наявні індекси для таблиць Author i Message.
SHOW INDEX FROM author;
SHOW INDEX FROM message;
2. Створимо новий індекс для таблиці Author i Message. У БД є декілька запитів, які здійснюють вибірку даних за логіном автора (поле login), за датою написання повідомлення (поле posted) тощо. Cтворення індексів для цих полів повинно оптимізувати виконання запитів.
CREATE INDEX authorINDX3 ON author (authorID, login); SHOW INDEX FROM author;
CREATE UNIQUE INDEX mposted_indx ON message (authorID, posted); SHOW INDEX FROM message;
