Базы данных и язык SQL - Лекция 2
←
→
Транскрипция содержимого страницы
Если ваш браузер не отображает страницу правильно, пожалуйста, читайте содержимое страницы ниже
Базы данных и язык SQL Лекция 2
Нормализация и нормальные формы Нормальная форма — требование, предъявляемое к структуре таблиц в теории реляционных баз данных для устранения из базы избыточных функциональных зависимостей между атрибутами (полями таблиц). Процесс преобразования отношений базы данных к виду, отвечающему нормальным формам, называется нормализацией. Нормализация предназначена для приведения структуры БД к виду, обеспечивающему минимальную логическую избыточность, и не имеет целью уменьшение или увеличение производительности работы или же уменьшение или увеличение физического объёма базы данных. Конечной целью нормализации является уменьшение потенциальной противоречивости хранимой в базе данных информации.
1NF Переменная отношения находится в первой нормальной форме (1NF) тогда и только тогда, когда каждое из значений его полей атомарно. Исходная ненормализованная (то Номер есть не являющаяся правильным Сотрудник телефона представлением некоторого отношения) 283-56-82 Иванов И. И. таблица: 390-57-34 Петров П. П. 708-62-34 Таблица, приведённая к 1NF (являющаяся правильным Номер Сотрудник телефона представлением некоторого Иванов И. И. 283-56-82 отношения): Иванов И. И. 390-57-34 Петров П. П. 708-62-34
2NF Для второй нормальной формы (2NF) таблица должна находиться в первой нормальной форме. Любое её поле, не входящее в состав первичного ключа, функционально полно должно зависеть от первичного ключа. Например, пусть в следующем отношении первичный ключ образует пара атрибутов {Сотрудник, Должность}: Сотрудник Должность Зарплата Наличие компьютера Гришин Кладовщик 20000 Нет Васильев Программист 40000 Есть Иванов Кладовщик 25000 Нет Зарплату сотруднику каждый начальник устанавливает сам (хотя её границы зависят от должности). Наличие же компьютера у сотрудника зависит только от должности, то есть зависимость от первичного ключа неполная. В результате приведения к 2NF исходное отношение следует декомпозировать (логически разбить) на два отношения: Сотрудник Должность Зарплата Наличие Должность компьютера Гришин Кладовщик 20000 Кладовщик Нет Васильев Программист 40000 Программист Есть Иванов Кладовщик 25000
3NF Для третьей нормальной формы (3NF) таблица должна находиться во второй нормальной форме. Любой её не ключевой атрибут функционально зависит только от первичного ключа. Рассмотрим в качестве примера отношение, которое находится во 2NF, но не соответствует 3NF. Сотрудник Отдел Телефон Гришин Бухгалтерия 11-22-33 Васильев Бухгалтерия 11-22-33 Петров Снабжение 44-55-66 В отношении атрибут «Сотрудник» является первичным ключом. Личных телефонов у сотрудников нет, и телефон сотрудника зависит исключительно от отдела. Таким образом, в отношении существуют следующие функциональные зависимости: Сотрудник → Отдел, Отдел → Телефон, Сотрудник → Телефон. Зависимость Сотрудник → Телефон является побочной, следовательно, отношение не находится в 3NF. В результате разделения отношения получаются два отношения, находящиеся в 3NF: Отдел Телефон Сотрудник Отдел Бухгалтерия 11-22-33 Гришин Бухгалтерия Снабжение 44-55-66 Васильев Бухгалтерия Петров Снабжение
SQL. NULL id name org salary NULL в Системах управления базами данных (СУБД) — специальное значение 1 Гришин NULL 10000 (псевдозначение), которое может быть 2 Васильев IT 15000 записано в поле таблицы базы данных (БД). NULL соответствует понятию 3 Петров Снабжение NULL «пустое поле», то есть «поле, не содержащее 4 Иванов IT 20000 никакого значения». Введено для того, чтобы различать в полях БД пустые (визуально не отображаемые) значения (например, строку нулевой длины) и отсутствующие значения (когда в поле не записано вообще никакого значения, даже пустого). NULL означает отсутствие, неизвестность информации. Значение NULL не является значением в полном смысле слова: по определению оно означает отсутствие значения и не принадлежит ни одному типу данных. Поэтому NULL не равно ни логическому значению FALSE, ни пустой строке, ни нулю. При сравнении NULL с любым значением будет получен результат NULL, а не FALSE и не 0. Более того, NULL не равно NULL! Для того, чтобы, например, извлечь из таблицы всех работников, у которых не указана (NULL) заработная плата либо не указан отдел, в котором они работают, необходимо выполнить запрос вида: name SELECT name FROM Employees Гришин WHERE org IS NULL Петров OR salary IS NULL; --- в проверке никаких знаков равенства! Только IS (NOT) NULL!
SQL. JOIN Ключевое слово join в SQL используется при построении select- выражений. Инструкция JOIN позволяет объединить колонки из нескольких таблиц в одну. Объединение происходит временное и целостность таблиц не нарушается. Существует три типа join-выражений: inner join; outer join; cross join; В свою очередь, outer join может быть left, right и full (слова inner и outer обычно опускаются). В качестве примера возьмём две простые таблицы (таблица А с работниками ссылается на таблицу B с организациями) и сконструируем для них SQL-выражения с использованием join. id name Id_B id name 1 Гришин 1 1 Бухгалтерия 2 Васильев 2 2 IT 3 Петров 3 3 Снабжение 4 Иванов NULL 4 Охрана
INNER JOIN id name Id_B id name 1 Гришин 1 1 Бухгалтерия 2 Васильев 2 2 IT 3 Петров 3 3 Снабжение 4 Иванов NULL 4 Охрана id name Id_B Id name SELECT * FROM a 1 Гришин 1 1 Бухгалтерия JOIN b 2 Васильев 2 2 IT ON a.id_B = b.id 3 Петров 3 3 Снабжение Обратите внимание на диаграмму множеств. Внутреннее соединение INNER JOIN производит выборку только тех записей, которые соответствуют пересечению таблиц А и В. Работник «Иванов» из таблицы А не нашёл себе соответствий в таблице В, также, как и вид организации «Охрана» из таблицы В не привязана ни к одному работнику. Поэтому данные значения не попали в конечный результат выборки.
LEFT OUTER JOIN id name Id_B id name 1 Гришин 1 1 Бухгалтерия 2 Васильев 2 2 IT 3 Петров 3 3 Снабжение 4 Иванов NULL 4 Охрана id name Id_B Id name SELECT * 1 Гришин 1 1 Бухгалтерия FROM a 2 Васильев 2 2 IT LEFT JOIN b 3 Петров 3 3 Снабжение ON a.id_B = b.id 4 Иванов NULL NULL NULL Левостороннее внешнее соединение LEFT OUTER JOIN производит полный выбор записей из таблицы А с соответствующими записями (если таковые имеются) таблицы B. Если совпадения нет, то правая часть будет содержать NULL.
RIGHT OUTER JOIN id name Id_B id name 1 Гришин 1 1 Бухгалтерия 2 Васильев 2 2 IT 3 Петров 3 3 Снабжение 4 Иванов NULL 4 Охрана id name Id_B Id name SELECT * 1 Гришин 1 1 Бухгалтерия Table A Table B FROM a 2 Васильев 2 2 IT RIGHT JOIN b 3 Петров 3 3 Снабжение ON a.id_B = b.id NULL NULL NULL 4 Охрана Правостороннее внешнее соединение действует по аналогии с LEFT JOIN’ом. RIGHT OUTER JOIN производит полный выбор записей из таблицы В с соответствующими записями (если таковые имеются) таблицы А. Если совпадения нет, то правая часть будет содержать NULL.
FULL OUTER JOIN id name Id_B id name 1 Гришин 1 1 Бухгалтерия 2 Васильев 2 2 IT 3 Петров 3 3 Снабжение 4 Иванов NULL 4 Охрана id name Id_B Id name 1 Гришин 1 1 Бухгалтерия SELECT * 2 Васильев 2 2 IT FROM a 3 Петров 3 3 Снабжение FULL JOIN b 4 Иванов NULL NULL NULL ON a.id_B = b.id NULL NULL NULL 4 Охрана Полное внешнее объединение FULL OUTER JOIN производит выборку множества всех записей из таблицы А и B с соответствующими записями с обеих сторон при их наличии. Если совпадения нет, отсутствующая сторона будет содержать NULL. Обратите внимание на две последних строки в итоговой выборке.
CROSS JOIN id name Id_B Id name Так же существует выборка перекрестного 1 Гришин 1 1 Бухгалтерия соединения (называемое ещё 1 Гришин 1 2 IT декартовым произведением), CROSS JOIN, 1 Гришин 1 3 Снабжение с перебором все вариантов, 1 Гришин 1 4 Охрана которое сложно объяснить диаграммами: 2 Васильев 2 1 Бухгалтерия 2 Васильев 2 2 IT SELECT * 2 Васильев 2 3 Снабжение FROM a 2 Васильев 2 4 Охрана CROSS JOIN b; 3 Петров 3 1 Бухгалтерия ---(ещё можно написать запрос как 3 Петров 3 2 IT ---SELECT * FROM a, b) 3 Петров 3 3 Снабжение Данное перекрестное соединение выбирает 3 Петров 3 4 Охрана буквально "всё ко всему", в результате мы 4 Иванов NULL 1 Бухгалтерия получим 4 x 4 = 16 записей, т.е. намного 4 Иванов NULL 2 IT больше, чем в оригинале мы имеем 4 Иванов NULL 3 Снабжение в таблицах. 4 Иванов NULL 4 Охрана
Работа с множествами Прежде чем начать описания функций и их свойств в SQL, работающих со множествами – дадим определение термину “множество” на языке SQL. Ведь многим из нас известно, что множество - это один из ключевых объектов математики, в частности, теории множеств и логики. По определению Бертрана Рассела: “Множество – совокупность различных элементов, мыслимая как единое целое” . А сейчас переместим это определение в базу данных и увидим, что вывод любого запроса можно принять за множество. Наверное у вас возникнет вопрос в виде: “И что же это нам дает?” Ответ прост – применение некоторых свойств и операций, присущих множествам. Сейчас мы с вами разберем, что это за операции и как они реализованы в SQL.
Объединение. UNION Объединением двух множеств A и B называется множество, содержащее в себе все элементы исходных множеств, и обозначается как A ∪ B. В языке SQL ключевое слово UNION применяется для объединения результатов двух SQL- запросов в единую таблицу, состоящую из схожих строк. Оба запроса должны возвращать одинаковое число столбцов и совместимые типы данных в соответствующих столбцах. Оператор указывается между запросами. В упрощенном виде это выглядит следующим образом: UNION [ALL] UNION [ALL] .....; По умолчанию любые дублирующие записи автоматически скрываются(своего рода default- ный DISTINCT), если не использовано выражение UNION ALL. Необходимо отметить, что UNION сам по себе не гарантирует порядок строк. Строки из второго запроса могут оказаться в начале, в конце или вообще перемешаться со строками из первого запроса. В случаях, когда требуется определенный порядок, необходимо использовать выражение ORDER BY.
Объединение. UNION Как выглядит объединение множеств на языке SQL: person amount sales2005 sales2006 Иван 1000 person amount person amount Алексей 2000 Иван Алексей 1000 2000 ∪ Иван Алексей 2000 2000 = Иван Сергей 2000 5000 Сергей 5000 Петр 35000 Петр 35000 (SELECT * FROM sales2005) UNION (SELECT * FROM sales2006); В результате отобразятся две строки с Иваном, так как эти строки различаются значениями в столбцах. Но при этом в результате присутствует лишь одна строка с Алексеем, поскольку значения в person amount столбцах полностью совпадают. Применение UNION ALL дает Иван 1000 другой результат, так как дубликаты не скрываются. Выполнение Иван 2000 запроса: Алексей 2000 Алексей 2000 (SELECT * FROM sales2005) UNION ALL Сергей 5000 (SELECT * FROM sales2006); даст следующий результат: Петр 35000
Пересечение. Intersect Пересечение — множество, состоящее из элементов, которые одновременно принадлежат всем данным множествам. Обозначается как A ⋂ B. То есть, это те элементы множеств, которые есть во всех рассматриваемых множествах. Для пересечение множеств на языке SQL есть функция INTERSECT, которая также как и UNION обладает ограничением на результат запросов, которые должны быть совместимы по объединению, т.е. содержать одинаковое количество столбцов, и каждый столбец первого запроса должен быть того же типа данных (или автоматически приводиться к нему), что и находящийся в том же месте столбец второго запроса. Также, пересечение не игнорирует поля, которые содержит значения null. INTERSECT INTERSECT .....;
Пересечение. Intersect Как выглядит пересечение множеств на языке SQL: sales2005 sales2006 person amount person amount person Иван 1000 Иван 2000 Иван Алексей 2000 ⋂ Алексей 2000 = Алексей Сергей 5000 Петр 35000 (SELECT person FROM sales2005) INTERSECT (SELECT person FROM sales2006); В результате отобразятся две строки – с Алексеем и с Иваном, так как эти строки находятся в обеих таблицах.
Разность. Minus/Except Разность двух множеств — это операция, результатом которой является множество, в которое входят все элементы первого множества, не входящие во второе множество. A\B означает множество элементов, принадлежащих A, но не принадлежащих B. В языке SQL нет стандарта для оператора разности множеств, поэтому он может в некоторых СУБД принимать значение MINUS, в других – EXCEPT. В любом случае, как и UNION, оператор разности обладает ограничением на результат запросов, которые должны быть совместимы по объединению, т.е. содержать одинаковое количество столбцов, и каждый столбец первого запроса должен быть того же типа данных (или автоматически приводиться к нему), что и находящийся в том же месте столбец второго запроса. MINUS/EXCEPT MINUS/EXCEPT .....;
Разность. Minus/Except Как выглядит разность множеств на языке SQL (версия для СУБД MS SQL Server): sales2005 sales2006 person amount person amount Иван 1000 Иван 2000 person Алексей 2000 \ Алексей 2000 = Сергей Сергей 5000 Петр 35000 (SELECT person FROM sales2005) EXCEPT (SELECT person FROM sales2006); В результате отобразится строка с Сергеем, уникальным именем для sales2005, т.к. все остальные имена были исключены множеством имён sales2006.
Lifehack Попробуем, используя знания работы со множествами, сделать финт такого рода: (A \ B) ∪ (B \ A) Т.е., вычленим из двух выборок уникальные записи, обойдя пересечения. Нам необходимы все данные из таблицы sales2005, которых нет в sales2006 и наоборот – всё из sales2006, чего нет в sales2005. Делается это так (версия для СУБД MS SQL Server): (SELECT person FROM sales2005 EXCEPT SELECT person FROM sales2006); ---(A \ B) UNION ---∪ (SELECT person FROM sales2006 EXCEPT SELECT person FROM sales2005); ---(B \ A) Подумайте, как ещё можно добиться такого же результата.
Домашнее задание 1) по книге Цыганкова/Мальцева – читать с самого начала до пункта 3.4 включительно; 2) Грабер М. Введение в SQL – читать главы 8, 9, 14 полностью. 3) на сайте SQL-EX.RU выполнить к следующему занятию задачи 6, 7, 8 (решить через JOIN), 9, 16, 23, 34, 35, 36, 38, 40, 44, 45, 48, 49, 50.
До встречи, друзья
Вы также можете почитать