Базы данных. Курс лекций
.pdf
Таблица «Сотрудники»
№ со- |
ФИО |
Долж- |
Отдел |
труд- |
|
ность |
|
ника |
|
|
|
1 |
Иванов И. И. |
инженер |
10 |
|
|
|
|
2 |
Петров П. П. |
бухгалтер |
20 |
|
|
|
|
3 |
Васин В. В. |
прораб |
10 |
|
|
|
|
… |
… |
… |
… |
|
|
|
|
Таблица «Информация о сотрудниках»
№ со- |
Год |
Число |
… |
труд- |
рожд. |
детей |
.. |
ника |
|
|
|
1 |
1960 |
2 |
… |
|
|
|
|
2 |
1958 |
3 |
… |
|
|
|
|
3 |
1970 |
2 |
… |
|
|
|
|
… |
… |
… |
… |
|
|
|
|
Рис. 14. Связь «один-к-одному»
3.4.3. Отношение «многие-ко-многим»
Отношение «многие-ко-многим» имеет место, когда:
а) записи в родительской таблице может соответствовать больше одной записи в дочерней таблице;
б) записи в дочерней таблице может соответствовать больше одной записи в родительской таблице.
Таблица «Учебные группы |
|
|
Таблица «Преподаватели» |
|
||
и дисциплины» |
|
|
|
|
|
|
|
|
|
|
|
|
|
Груп- |
Предмет |
№ пре- |
№ пре- |
ФИО преподава- |
Кафед- |
|
па |
|
под. |
|
под. |
теля |
ра |
М-101 |
Матем. анализ |
10 |
|
10 |
Краснов Ю. Б. |
ММ |
|
|
|
|
|
|
|
ФК-101 |
Матем. анализ |
12 |
|
12 |
Володин В. Н. |
ММ |
|
|
|
|
|
|
|
М-101 |
Философия |
25 |
|
15 |
Булгаков В. М. |
Ф |
|
|
|
|
|
|
|
МА-101 |
Эк. теория |
25 |
|
25 |
Савушкин И. И. |
ЭТ |
|
|
|
|
|
|
|
М-101 |
Логика |
12 |
|
50 |
Подушкин А. В. |
ФИ |
|
|
|
|
|
|
|
… |
… |
… |
|
… |
… |
… |
|
|
|
|
|
|
|
Рис. 15. Связь «многие-ко-многим»
30
На рис. 15 показаны таблицы, состоящие в отношении «многие-ко-многим». Каждой учебной группе соответствует несколько преподавателей. Каждый преподаватель может вести, во-первых, несколько разных предметов и, во-вторых, преподавать в разных группах.
Многие СУБД не поддерживают связи «многие-ко-многим» на уровне индексов и ссылочной целостности, хотя и позволяют реализовывать ее в таблицах неявным образом. Аналогично многие CASE-средства (программы для разработки структуры базы данных в виде диаграмм и генерации на их основе физической базы данных) также не позволяют определять эту связь между таблицами проектируемой базы данных. Считается, что всякая связь «многие-ко-многим» может быть заменена на одну или более связь «один-ко-многим». Хотя это так, целесообразность применения такой связи должна рассматриваться прежде всего в контексте разрабатываемой базы данных и приложения для работы с ней, и там, где это удобно, такая связь должна реализовываться.
3.5. Ссылочная целостность и каскадные воздействия
Рассмотрим наиболее часто встречающуюся в базах данных связь «один-ко- многим» (рис. 16). Как можно заметить, дочерняя и родительская таблицы связаны между собой по общему полю «Товар». Назовем это поле полем связи.
Возможны два вида изменений, которые приведут к утере связей между записями в родительской и дочерней таблицах:
•изменение значения поля связи в записи родительской таблицы без изменения значений полей связи в соответствующих записях дочерней таблицы;
•изменение значения поля связи в одной из записей дочерней таблицы без соответствующего изменения значения полей связи в родительской и дочерней таблицах.
Разберем первый случай. На рис. 16 показано изменение значения поля «Товар» с «Сахар» на «Рафинад» в таблице «Товары». В таблице «Отпуск товаров» значение поля связи «Сахар» осталось прежним.
31
Таблица «Товары» |
|
|
Таблица «Отпуск товаров» |
|||
|
|
|
|
|
Дата |
|
Товар |
Ед. изм. |
Цена ед. |
Товар |
Кол-во ед. |
||
|
|
|
|
|
10.01.2006 |
|
Рафинад |
кг |
35 |
|
Сахар |
100 |
|
|
|
|
|
|
12.01.2006 |
|
Макароны |
кг |
40 |
|
Сахар |
200 |
|
|
|
|
|
|
14.01.2006 |
|
Куры |
кг |
150 |
|
Сахар |
50 |
|
|
|
|
|
|
10.01.2006 |
|
Вода |
Бут. 1 л |
30 |
|
Макароны |
1000 |
|
|
|
|
|
|
11.01.2006 |
|
|
|
|
|
Макароны |
500 |
|
|
|
|
|
|
10.01.2006 |
|
|
|
|
|
Вода |
2000 |
|
|
|
|
|
|
12.01.2006 |
|
|
|
|
|
Вода |
3000 |
|
|
|
|
|
|
|
|
Рис. 16. Нарушение целостности базы данных – записи с товаром «Сахар» (таблица «Отпуск товаров») не имеют родительской записи
В результате:
• в дочерней таблице «Отпуск товаров» для товара «Рафинад» (таблица «Товары») нет сведений о его отпуске со склада;
• некоторые записи таблицы «Отпуск товаров» содержат сведения об отпуске товара («Сахар»), о котором нет информации в таблице «Товары».
Таблица «Товары» |
|
|
Таблица «Отпуск товаров» |
|||
|
|
|
|
|
Дата |
|
Товар |
Ед. изм. |
Цена ед. |
Товар |
Кол-во |
||
|
|
|
|
|
|
ед. |
|
|
|
|
|
10.01.2006 |
|
Сахар |
кг |
35 |
|
Рафинад |
100 |
|
|
|
|
|
|
12.01.2006 |
|
Макароны |
кг |
40 |
|
Сахар |
200 |
|
|
|
|
|
|
14.01.2006 |
|
Куры |
кг |
150 |
|
Сахар |
50 |
|
|
|
|
|
|
10.01.2006 |
|
Вода |
Бут. 1 л |
30 |
|
Макароны |
1000 |
|
|
|
|
|
|
11.01.2006 |
|
|
|
|
|
Макароны |
500 |
|
|
|
|
|
|
10.01.2006 |
|
|
|
|
|
Вода |
2000 |
|
|
|
|
|
|
12.01.2006 |
|
|
|
|
|
Вода |
3000 |
|
|
|
|
|
|
|
|
Рис. 17. Нарушение целостности базы данных — записи с товаром «Рафинад» (таблица «Отпуск товаров») не имеют родительской записи
32
Разберем второй случай. Пусть в одной из записей таблицы «Отпуск товаров» значение поля связи «Сахар» изменилось на «Рафинад» (рис. 17). В результате:
•в дочерней таблице «Отпуск товаров» недостоверны сведения об отпуске со склада товара «Сахар» (таблица «Товары»);
•одна из записей таблицы «Отпуск товаров» содержит данные об отпуске товара («Рафинад»), сведения о котором (такие, как единица измерения и цена за единицу) отсутствуют в таблице «Товары».
И в первом, и во втором случае мы наблюдаем нарушение целостности базы данных, поскольку информация в ней становится недостоверной. Следовательно, нужно блокировать действия, которые нарушают целостность связей между таблицами, которую называют ссылочной целостностью. Когда говорят о ссылочной целостности, имеют в виду совокупность связей между отдельными таблицами во всей БД. Нарушение хотя бы одной такой связи делает информацию в БД недостоверной.
Чтобы предотвратить потерю ссылочной целостности, используется механизм каскадных изменений. Он состоит в обеспечении следующих требований:
•необходимо запретить изменение поля связи в записи дочерней таблицы без синхронного изменения полей связи в родительской и дочерней таблицах; обычно инициатива изменения поля связи реализуется в записи родительской таблицы;
•при изменении поля связи в записи родительской таблицы следует синхронно изменить значения полей связи в соответствующих записях дочерней таблицы;
•при удалении записи в родительской таблице следует удалить соответствующие записи в дочерней таблице.
Данные изменения или удаления в записях дочерней таблицы при изменении (удалении) записи родительской таблицы называются каскадными изменениями и каскадными удалениями.
33
Замечание 1. Существует другая разновидность каскадного удаления: при удалении родительской записи в записях дочерних таблиц значения полей связи обнуляются. Эта разновидность применяется редко.
Замечание 2. Обычно занесение записей в дочернюю таблицу осуществляется так: выбирается значение родительской записи (например, из выпадающего списка), значение поля связи фиксируется и затем автоматически заносится в поля связи дочерних записей. Метод, когда пользователь вручную заносит значения полей связи в дочерние записи, непопулярен: пользователь может внести одинаковое по смыслу, но разное по написанию значение («Сахар», «сахар»). Много реже практикуется способ ввода дочерних записей без указания значения поля связи. Затем записи родительской и дочерних таблиц «связываются».
Каскадные изменения могут блокироваться: или одновременно изменения и удаления, или изменения или удаления по отдельности. Необходимость разрешения или запрещения каскадных изменений обычно реализуется в СУБД при определении связей между таблицами. Собственно, таким образом и происходит создание ссылочной целостности. Обычно в СУБД для реализации ссылочной целостности в дочерней таблице создают внешний ключ (см. ниже), ссылающийся на родительскую таблицу, и указывают вид каскадных воздействий. В последующем СУБД сама при необходимости реализует декадные воздействия данного вида для указанных таблиц.
3.6. Понятие внешнего ключа
Для обеспечения ссылочной целостности в дочерней таблице создается внешний ключ. Во внешний ключ входят поля связи дочерней таблицы. Для связей типа «один-ко-многим» внешний ключ по составу полей должен совпадать с первичным ключом родительской таблицы или – реже – с частью первичного ключа (в этом случае следует признать, что нормализация таблиц БД произведена не полностью). Иногда внешний ключ называют вторичным ключом.
По определениям первичного и внешнего (вторичного) ключей СУБД автоматически строит индексы (см. ниже). Индекс, соответствующий внешнему (вторичному) ключу, используется для реализации связи родительской и дочерних
34
таблиц. Механизм индексов основан на понятии методов доступа, поэтому рассмотрим их подробнее.
3.7. Индексы и методы доступа
Индексы представляют собой механизмы быстрого доступа к данным в таблицах БД.
Сущность индексов состоит в том, что они хранят значения индексных полей (т. е. полей, по которым построен индекс) и указатель на запись в таблице. Например, если имеется таблица (рис. 18), то с логической точки зрения индексы выглядят, как на рис. 19.
Порядковый № за- |
Дата прихода то- |
Наименование то- |
Количество, кг |
писи |
вара |
вара |
|
1 |
10.01.2007 |
Сахар |
10 |
2 |
12.01.2007 |
Картофель |
50 |
3 |
12.01.2007 |
Свекла |
20 |
4 |
14.01.2007 |
Сахар |
50 |
5 |
14.01.2007 |
Свекла |
10 |
6 |
16.01.2007 |
Сливы |
4 |
Рис. 18. Физическая структура таблицы
Следовательно, если нужно выбрать все записи с наименованием товара «Свекла», нет нужды просматривать всю таблицу.
По дате прихода товара |
По наименованию това- |
По количеству |
||||
|
|
|
ра |
|
|
|
Дата прихо- |
№ записи |
Товар |
|
№ записи |
Количество |
№ записи |
да |
|
|
|
|
|
|
|
|
|
|
|
|
|
10.01.2007 |
1 |
Картофель |
|
2 |
4 |
6 |
|
|
|
|
|
|
|
12.01.2007 |
2 |
Сахар |
|
1 |
10 |
1 |
|
|
|
|
|
|
|
12.01.2007 |
3 |
Сахар |
|
4 |
10 |
5 |
|
|
|
|
|
|
|
14.01.2007 |
4 |
Свекла |
|
3 |
20 |
3 |
|
|
|
|
|
|
|
14.01.2007 |
5 |
Свекла |
|
5 |
50 |
2 |
|
|
|
|
|
|
|
16.01.2007 |
6 |
Сливы |
|
6 |
50 |
4 |
|
|
|
|
|
|
|
Рис. 19. Логическая структура индексов
35
Достаточно найти в индексе, построенном по столбцу «Наименование товара», первый указатель на запись, содержащую товар «Свекла», и считать из таблицы эту запись, а затем повторить то же для всех иных указателей в индексе на записи с товаром «Свекла». Если нужно считать все записи из таблицы, отвечающие условию «Количество > 16», достаточно найти в индексе, построенном по столбцу «Количество», первую строку с количеством больше 16, считать запись из таблицы по указателю на нее, записанному в индексе, и в дальнейшем повторить эти действия для всех записей, у которых значение «Количество» в индексе больше 16.
Вдействительности индексы имеют более сложную организацию, но думается, что с логической точки зрения при проектировании баз данных полезнее представлять их структуру и их принцип использования так, как это сделано выше.
Вописанном выше нехитром примере использования индексов мы сталки-
ваемся с двумя методами доступа к записям в таблице – последовательным и индексно-последовательным. При этом индексно-последовательный доступ неявно использует прямой и последовательный доступ.
При последовательном методе доступа для выполнения запроса к таблице БД просматриваются все записи таблицы, от первой к последней. Нет смысла говорить, что этот метод совершенно неэффективен (зачем просматривать 100 000 записей, если удовлетворяют условию запроса всего 2?). Неэффективность выражается прежде всего в потере быстродействия и напрасной трате вычислительных ресурсов. Время выполнения запроса прямо пропорционально числу записей в таблице.
При индексно-последовательном методе доступа для выполнения запро-
са к таблице БД указатель в индексе устанавливается на первую строку, удовлетворяющую условию запроса (или его части), и считывается запись из таблицы по хранящемуся на нее в индексе указателю. Затем указатель в индексе перемещается на следующую строку, удовлетворяющую условию запроса (или его части), и из таблицы считывается запись. То же происходит для всех строк в индексе,
36
удовлетворяющих условию запроса (или его части). Процесс выборки прекращается, когда текущая строка в индексе перестанет удовлетворять условию запроса.
Заметим, что оговорка «удовлетворяющих условию запроса (или его части)» сделана специально, поскольку запросы, состоящие из более чем одного критерия поиска записей, приходится удовлетворять за несколько обращений к индексу. Например, для запроса «выдать все приходы свеклы или картофеля» может потребоваться сначала отыскать все записи по приходу свеклы, а затем – по приходу картофеля.
При индексно-последовательном доступе просматривается только часть индекса, а из таблицы читаются только записи, удовлетворяющие условию поис-
ка. Метод назван индексно-последовательным потому, что:
•поиск ведется по индексу, а не по самой таблице;
•поиск в индексе начинается только с первой строки, удовлетворяющей условию запроса или его части (так называемый прямой доступ);
•строки в индексе, начиная с такой записи, просматриваются все-таки
последовательно.
Втом случае, если в условия запроса входят поля, по которым не построено индексов, ищется иной пригодный индекс; если такого индекса нет, производится последовательный перебор записей таблицы БД.
При прямом методе доступа запись из таблицы выбирается непосредственно, по значению одного поля или группы полей, минуя переборы других записей.
Таким образом, индексно-последовательный метод доступа использует
прямой доступ при установке в индексе на первую строку, удовлетворяющую запросу или его части. После этого используется последовательный метод доступа для перемещения по строкам индекса.
Для «локальных» («персональных») СУБД типа Paradox, dBase индексы хранятся отдельно от основной таблицы БД – в виде отдельного файла. В случае их определения в «промышленных» («серверных») СУБД – таких как Oracle, Sybase, InterBase, SQL Server – индексы хранятся вместе с БД.
37
Как уже сказано выше, определения первичных и внешних ключей таблиц БД приводят к созданию индексов по полям, объявленным в составе первичных или внешних ключей. Дополнительные индексы создаются вручную или программно, если индексов, построенных по определениям первичных и внешних ключей, недостаточно для:
•обеспечения нужного порядка сортировки данных;
•оптимизации доступа к базе данных.
3.8. Нормализациятаблицприпроектированиибазыданных
При проектировании структуры новой БД определяют сущности (объекты, явления) предметной области, которые должны найти свое отражение в базе данных. Анализ предметной области обычно осуществляется:
•на основании существующих сведений о предметной области в широком или в узком смысле, т. е. в масштабах, в которых она должна быть представлена в создаваемой БД и работающих с ней приложениях;
•исходя из целей проектирования программной системы;
•на основании представления о том, какое место БД и работающие с ней приложения займут в структуре эксплуатирующей ее организации;
•на основании представлений о том, какие изменения деловых потоков организации последуют после внедрения программной системы в эксплуатацию.
Вконечном итоге анализ предметной области должен привести к созданию эскиза БД. Сначала желательно изобразить сущности и связи между ними. Как правило, каждой сущности в БД соответствует таблица. Затем – в эскизе второго порядка – для каждой таблицы БД приводится список полей записи.
Замечание. Несмотря на существование методик анализа предметных областей, построения эскизов БД (весьма полезных при больших объемах обрабатываемых данных и деловых правил в предметной области, нередко выходящих за рамки одновременного восприятия), необходимо отметить следующее:
•процесс определения окончательной структуры БД является циклическим, т. е. на разных этапах проектирования – начиная от эскиза структуры БД
38
изаканчивая опытной или даже промышленной эксплуатацией готовых программных систем – приходится возвращаться к структуре БД и вносить в нее изменения;
•в процессе моделирования предметной области участвуют такие субъективные факторы, как здравый смысл разработчика, его интуиция, привычки, личностное восприятие проблемы, стереотипы мышления и т. д. Поэтому различные разработчики наверняка предложат различные проекты структуры одной
итой же БД, хотя в узловых моментах, например в определении большей части сущностей и связей между ними, эти проекты должны быть похожи.
Следовательно, с одной стороны, процесс проектирования структур БД является процессом творческим, неоднозначным, с другой стороны, узловые его моменты могут быть формализованы.
Одной из таких формализаций является требование, согласно которому реляционная база данных должна быть нормализована (т. е. подвергнута процедуре нормализации). Рассмотрим, что это такое.
Процесс нормализации имеет своей целью устранение избыточности данных и заключается в приведении к третьей нормальной форме (3НФ).
Существует несколько нормальных форм — 1НФ, 2НФ, 3НФ, 4НФ, 5НФ, нормальная форма Бойса-Кодда (БКНФ). При практической разработке баз данных важны первые три — 1НФ, 2 НФ, 3НФ.
Первая нормальная форма (1НФ) требует, чтобы каждое поле таблицы
БД:
•было неделимым;
•не содержало повторяющихся групп.
Неделимость поля означает, что значение поля не должно делиться на более мелкие значения. Например, если в поле «Подразделение» содержится название факультета и название кафедры, требование неделимости не соблюдается и необходимо из данного поля выделить или название факультета, или кафедры в отдельное поле.
Повторяющимися являются поля, содержащие одинаковые по смыслу значения. Например, если требуется получить статистику продаж четырех товаров
39
