Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
К вопросу нормализации базы данных.doc
Скачиваний:
1
Добавлен:
15.09.2019
Размер:
174.08 Кб
Скачать

Var fRejs: file of record kRejs{код рейса}:integer;

Gp{город прибытия (конец маршрута)}:STRING; Sost{сведения об остановках}: ARRAY[1..50]

OF {для каждой из 50-ти остановок} RECORD NamO{наименование остановки}:STRING;

TypO:{тип населенного пункта-остановки (областной центр, райцентр, город, поселок городского типа, поселок, станица, станция)}:STRING;

DlO{длительность проезда до неё}:REAL; DlSt{длительность стоянки}:INTEGER END;

DSv{детальные сведения}: ARRAY[1..52] OF {для каждой из 52-х недель текущего года} RECORD Spb{сведения о проданных билетах}: ARRAY[1..7]

OF {для каждого из 7-ми дней этой недели} RECORD Vot{время отправления}:STRING;

Svg{список вагонов}: ARRAY[1..10] OF {для каждого из 10 вагонов} RECORD

Tvg{тип вагона (плацкарт, купе, мягкий)}:STRING;

KolMest{количество мест в вагоне}}:INTEGER;

Zvg {заполненность вагона}: ARRAY[1.. 351]

OF {для каждого места вагона} RECORD FIO{ФИО пассажира}:STRING;

Npv{порядковый номер остановки - пункта высадки}:STRING END END;

FIOnp{ФИО начальника поезда}:STRING; Spvg{список проводников}: ARRAY[1..10]

OF {для каждого из 10 вагонов} STRING {ФИО проводника} END END END

Необходимо провести заданное отношение к 3-ей нормальной форме.

***************************************************************************

Изучая структуру записей файла можно сделать одно замечание: с одной стороны для каждого дня недели приведен список вагонов, для каждого из которых определен тип вагона и список пассажиров, купивших в него билеты, с другой стороны задается список проводников поезда. Можно предположить, что каждый проводник прикреплен к определенному вагону и соответственно скорректировать структуру записи. С учетом данного замечания структура записи может быть представлена в следующем виде:

Var fRejs: file of

RECORD

KRejs{код рейса}:INTEGER;

Gp{город прибытия (конец маршрута)}:STRING;

Sost{сведения об остановках}: ARRAY[1..50]OF {для каждой из 50-ти

остановок}

RECORD

NamO{наименование остановки}:STRING;

TypO:{тип населенного пункта-остановки (областной центр, райцентр, город, поселок городского типа, поселок, станица, станция)}:STRING;

DlO{длительность проезда до неё}:REAL;

DlSt{длительность стоянки}:INTEGER

END;

DSv{детальные сведения}: ARRAY[1..52] OF {для каждой из 52-х недель

текущего года}

RECORD Spb{сведения о проданных билетах}: ARRAY[1..7]OF {для каждого из

7-ми дней этой недели}

RECORD Vot{время отправления}:STRING;

Svg{список вагонов}: ARRAY[1..10] OF {для каждого из 10 вагонов}

RECORD

Tvg{тип вагона (плацкарт, купе, мягкий)}:STRING;

KolMest{количество мест в вагоне}}:INTEGER;

FioProv: {Фамилия проводника} STRING;

Zvg{заполненность вагона}: ARRAY[1.. 35]OF {для каждого из 35-ти мест вагона}

RECORD

FIO{ФИО пассажира}:STRING;

Npv{порядковый номер остановки - пункта высадки}:STRING

END

END

FIOnp{ФИО начальника поезда}:STRING;

END;

END

END;

Рассмотрим один из вариантов декомпозиции данной структуры в множество таблиц реляционной базы данных

Можно заметить, что в данном примере каждая запись файла описана древообразной структурой, корневой вершине которой приписан номер рейса. Ниже приведено полное дерево, описывающее эту структуру:

Номер рейса:

Пункт назначения

Сведения об остановках:

1-я остановка:

Наименование остановки

Тип остановки

Длительность проезда

Длительность стоянки

2-я остановка:

Наименование остановки

Тип остановки

Длительность проезда

Длительность стоянки

. . . . . . . . . . . . .

50-я остановка:

Наименование остановки

Тип остановки

Длительность проезда

Длительность стоянки

Номер недели:

1-я неделя:

Номер дня недели:

1 день:

Время отправления

Фамилия начальника поезда

Список вагонов:

1-ый вагон:

Тип вагона

Количество мест в вагоне

ФИО проводника

Количество проданных билетов

Места:

первое место:

ФИО пассажира

Порядковый номер остановки

второе место:

ФИО пассажира

Порядковый номер остановки

. . . . . . . . . . . . . . .

35-е место2:

ФИО пассажира

Порядковый номер остановки

. . . . . . . . . . . . . .

10-ый вагон:

Тип вагона

ФИО проводника

Количество проданных билетов

Места:

первое место:

ФИО пассажира

Порядковый номер остановки

второе место:

ФИО пассажира

Порядковый номер остановки

. . . . . . . . . . . . . . .

35-е место:

ФИО пассажира

Порядковый номер остановки

. . . . . . . . . .

7 день:

Время отправления

Список вагонов:

1-ый вагон:

Тип вагона

ФИО проводника

Количество проданных билетов

Места:

первое место:

ФИО пассажира

Порядковый номер остановки

второе место:

ФИО пассажира

Порядковый номер остановки

. . . . . . . . . . . . . . .

35-е место:

ФИО пассажира

Порядковый номер остановки

. . . . . . . . . . . . . .

10-ый вагон:

Тип вагона

ФИО проводника

Количество проданных билетов

Места:

первое место:

ФИО пассажира

Порядковый номер остановки

второе место:

ФИО пассажира

Порядковый номер остановки

. . . . . . . . . . . . . . .

35-е место:

ФИО пассажира

Порядковый номер остановки

. . . . . . . . . . . . . . .

52-я неделя:

День недели:

1 день:

Время отправления

Список вагонов:

1-ый вагон:

Тип вагона

ФИО проводника

Количество проданных билетов

Места:

первое место:

ФИО пассажира

Порядковый номер остановки

второе место:

ФИО пассажира

Порядковый номер остановки

. . . . . . . . . . . . . . .

35-е место:

ФИО пассажира

Порядковый номер остановки

. . . . . . . . . . . . . .

10-ый вагон:

Тип вагона

ФИО проводника

Количество проданных билетов

Места:

первое место:

ФИО пассажира

Порядковый номер остановки

второе место:

ФИО пассажира

Порядковый номер остановки

. . . . . . . . . . . . . . .

35-е место:

ФИО пассажира

Порядковый номер остановки

. . . . . . . . . .

7 день:

Время отправления

Список вагонов:

1-ый вагон:

Тип вагона

ФИО проводника

Количество проданных билетов

Места:

первое место:

ФИО пассажира

Порядковый номер остановки

второе место:

ФИО пассажира

Порядковый номер остановки

. . . . . . . . . . . . . . .

35-е место:

ФИО пассажира

Порядковый номер остановки

. . . . . . . . . . . . . .

10-ый вагон:

Тип вагона

ФИО проводника

Количество проданных билетов

Места:

первое место:

ФИО пассажира

Порядковый номер остановки

второе место:

ФИО пассажира

Порядковый номер остановки

. . . . . . . . . . . . . . .

35-е место:

ФИО пассажира

Порядковый номер остановки

Для такой иерархической структуры достаточно легко находить функциональные зависимости между атрибутами исходного отношения. В частности, атрибут, приписанный некоторой вершине в дереве, функционально зависит от всех или части атрибутов расположенных на пути, ведущем от корня дерева к заданной вершине. В частности, в нашем случае можно описать зависимости:

(код рейса, номер остановки) -> наименование остановки;

(код рейса, номер остановки) -> тип остановки;

Вообще говоря, множество связей не ограничивается связями между атрибутами, описывающими вершины, находящиеся на одном пути от корня к листу, и может являться более широким. Например, количество мест в вагоне определяется типом вагона (естественно считать количество мест в купейном, плацкартном и общем вагоне разным). Поэтому можно говорить о зависимости: тип вагона -> количество мест, которое связывает вершины одного уровня.

Кроме того, нередко возникает необходимость объединения некоторых атрибутов, которое достигается определением новых атрибутов. Для данного примера, поскольку наименование остановки и тип остановки описывают один и тот же объект, можно ввести атрибут код остановки, который однозначно определяет как наименование, так и тип населенного пункта. После введения такого атрибута появляются дополнительные связи:

(код рейса, номер остановки) -> код остановки;

код остановки -> наименование остановки

код остановки -> тип остановки;

Приведенное представление не является единственным. Можно предложить различные преобразование, которое меняет структуру дерева с сохранением семантических связей. Например, любое дерево может быть свернуто в одноуровневое дерево, состоящее из единственной корневой вершины и листьев, причем каждый лист описывается некоторой сложной структурой. Для каждого листа в дереве можно построить вектор, который описывает метки пути, ведущего из корня дерева в соответствующий лист. Такого рода преобразования позволяют описать информацию о рейсах в виде одного отношения (таблицы). Нетрудно заметить, что такой способ описания не является хорошим: он содержит избыточную информацию (наименования одного и того же населенного пункта могут появляться многократно для различных рейсов, одни и те же проводники могут в разное время обслуживать различные поезда и т.д.); с другой стороны информация о количестве остановок, о заполнении мест в вагонах меняется от рейса к рейсу (к чему хранить информацию для места, на который не был продан билет), поэтому фиксированная структура таблицы может привести к большому количеству незаполненных клеток.

Рассмотрим приведение таблицы к 1NF.

Поскольку на первом уровне находятся три вершины, из которых только одна содержит атомарную информацию, а остальные содержат сложные атрибуты, произведем выделение этой информации в виде отдельных таблиц:

Шаг 1:

Таблица Rejs:

KodRejs: {Номер рейса} : INTEGER;

Gp {город прибытия (конец маршрута)}:STRING;

Таблица Ost:

KodRejs: (Номер рейса) : INTEGER;

NomOst {Номер остановки} : INTEGER;

NamO {наименование остановки}:STRING;

TypO:{тип населенного пункта-остановки (областной центр, райцентр, город, поселок городского типа, поселок, станица, станция)}:STRING;

DlO{длительность проезда до неё}:REAL;

DlSt{длительность стоянки}:INTEGER;

Для идентификации остановки введен атрибут NomOst, который характеризует порядковый номер остановки в рейсе.

Таблица DetSved:

KodRejs: (Номер рейса) : INTEGER;

NomNed {Номер недели} : INTEGER;

NomDen {номер дня недели}: INTEGER;

Sрb {сведения о проданных билетах}:структурный;

Детальные сведения относятся к определенному дню года, каждый день кодируется сложным атрибутом (NomNed,NomDen). Поскольку таблица DetSved содержит сложный атрибут(Sрb), выделим подчиненное отношение, спускаясь на один уровень вниз описанного выше дерева:

Шаг 2:

Таблица DetSved:

KodRejs: (номер рейса) : INTEGER;

NomNed {номер недели} : INTEGER;

NomDen {номер дня недели}: INTEGER;

Vot{время отправления}:STRING;

FIOnp{ФИО начальника поезда}:STRING;

Svg{список вагонов}: структурный

Шаг 3:

Продолжая декомпозицию таблицы DetSved, получим:

Таблица DetSved:

KodRejs: (номер рейса) : INTEGER;

NomNed {номер недели} : INTEGER;

NomDen {номер дня недели}: INTEGER;

Vot{время отправления}:STRING;

FIOnp{ФИО начальника поезда}:STRING;

Таблица Svg (список вагонов):

KodRejs: (номер рейса) : INTEGER;

NomNed {номер недели} : INTEGER;

NomDen {номер дня недели}: INTEGER;

NomVagon {номер вагона}: INTEGER;

Tvg{тип вагона (плацкарт, купе, мягкий)}:STRING;

KolMest (Количество мест) : INTEGER;

FioProv: {Фамилия проводника} STRING;

Zvg{заполненность вагона}: структурный

Вводится атрибут номер вагона (NomVagon)

Шаг 4:

Поскольку таблица Sved_Vagon содержит сложные атрибуты, выделим подчиненное отношение, спускаясь на один уровень описанного выше дерева:

Таблица Svg:

KodRejs: (номер рейса) : INTEGER;

NomNed {номер недели} : INTEGER;

NomDen {номер дня недели}: INTEGER;

NomVagon {номер вагона}: INTEGER;

Tvg{тип вагона (плацкарт, купе, мягкий)}:STRING;

FioProv: {Фамилия проводника} STRING;

Таблица Zvg (Заполненность вагона):

KodRejs: (номер рейса) : INTEGER;

NomNed {номер недели} : INTEGER;

NomDen {номер дня недели}: INTEGER;

NomVagon {номер вагона}: INTEGER;

NomMest{номер места}: INTEGER;

FIO{ФИО пассажира}:STRING;

Npv{порядковый номер остановки – пункта высадки}:STRING

Вводится атрибут номер места в вагоне (NomMest)

Шаг 4 завершает приведение таблицы к 1 нормальной форме. В результате получим базу данных, состоящую из 5 таблиц:

Таблица Rejs:

KodRejs: {Номер рейса} : INTEGER;

Gp {город прибытия (конец маршрута)}:STRING;

Таблица Ost:

KodRejs: (Номер рейса) : INTEGER;

NomOst {Номер остановки} : INTEGER;

NamO {наименование остановки}:STRING;

TypO:{тип населенного пункта-остановки (областной центр, райцентр, город, поселок городского типа, поселок, станица, станция)}:STRING;

DlO{длительность проезда до неё}:REAL;

DlSt{длительность стоянки}:INTEGER;

Таблица DetSved:

KodRejs: (Номер рейса) : INTEGER;

NomNed {Номер недели} : INTEGER;

NomDen {номер дня недели}: INTEGER;

Vot{время отправления}:STRING;

FIOnp{ФИО начальника поезда}:STRING;

Таблица Svg:

KodRejs: (Номер рейса) : INTEGER;

NomNed {Номер недели} : INTEGER;

NomDen {номер дня недели}: INTEGER;

NomVagon {номер вагона}: INTEGER;

Tvg{тип вагона (плацкарт, купе, мягкий)}:STRING;

KolMest (Количество мест) : INTEGER;

FioProv: {Фамилия проводника} STRING;

Таблица Zvg:

KodRejs: (Номер рейса) : INTEGER;

NomNed {Номер недели} : INTEGER;

NomDen {номер дня недели}: INTEGER;

NomVagon {номер вагона}: INTEGER;

NomMest{номер места}: INTEGER;

FIO{ФИО пассажира}:STRING;

Npv{порядковый номер остановки - пункта высадки}:STRING

Сведения об остановках встречаются в нескольких таблицах. Поскольку список остановок меняется от рейса к рейсу, то вполне резонно выделить этот список в отдельную таблицу. Введем в таблице Ost не ключевое поле KodO {код остановки}: INTEGER; (Заметим, что KodO не совпадает с атрибутом NomOst, поскольку атрибут KodO идентифицирует остановку, а атрибут NomOst является порядковым номером остановки для данного рейса);

Таблица Ost:

KodRejs: (Номер рейса) : INTEGER;

NomOst {Номер остановки} : INTEGER;

KodO {код остановки}: INTEGER;

NamO {наименование остановки}:STRING;

TypO:{тип населенного пункта-остановки (областной центр, райцентр, город, поселок городского типа, поселок, станица, станция)}:STRING;

DlO{длительность проезда до неё}:REAL;

DlSt{длительность стоянки}:INTEGER;

Изучая функциональные зависимости в таблице Ost, получим следующие функциональные зависимости:

(KodRejs,NomOst)  KodOst

(KodRejs,NomOst)  NamO

(KodRejs,NomOst)  TypO

KodOst  NamO (неключевой атрибут функционально зависит от неключевого)

KodOst  TypO

Согласно алгоритму приведения к третьей нормальной форме модифицированная таблица Ost разбивается на две:

Таблица Ost:

KodRejs: (Номер рейса) : INTEGER;

NomOst {Номер остановки} : INTEGER;

KodO {код остановки}: INTEGER;

DlO{длительность проезда до неё}:REAL;

DlSt{длительность стоянки}:INTEGER;

Таблица SpOst:

KodO {код остановки}: INTEGER;

NamO{наименование остановки}:STRING;

TypO:{тип населенного пункта-остановки (областной центр, райцентр, город, поселок городского типа, поселок, станица, станция)}:STRING;

Можно также предположить, что проводники из рейса выбираются из некоторого общего списка. Добавим в таблицу Svg атрибут KodProv {Код проводника}: INTEGER;

Таблица Svg:

KodRejs: (Номер рейса) : INTEGER;

NomNed {Номер недели} : INTEGER;

NomDen {номер дня недели}: INTEGER;

NomVagon {номер вагона}: INTEGER;

Tvg{тип вагона (плацкарт, купе, мягкий)}:STRING;

KolMest (Количество мест) : INTEGER;

KodProv: {Код проводника} INTEGER;

FioProv: {Фамилия проводника} STRING;

Для данного отношения имеем следующие функциональные связи:

(KodRejs,NomNed,NomDen,NomVagon)  KodProv

(KodRejs,NomNed,NomDen,NomVagon)  FioProv

KodProv  FioProv

Также заметим, что

(KodRejs,NomNed,NomDen,NomVagon)  Tvg

(KodRejs,NomNed,NomDen,NomVagon)  KolMest

Tvg  KolMest

Согласно алгоритму приведения к третьей нормальной форме модифицированная таблица Svg разбивается на три:

Таблица Svg:

KodRejs: (Номер рейса) : INTEGER;

NomNed {Номер недели} : INTEGER;

NomDen {номер дня недели}: INTEGER;

NomVagon {номер вагона}: INTEGER;

Tvg{тип вагона (плацкарт, купе, мягкbй)}:STRING;

KodProv: {Код проводника} INTEGER;

Таблица Prov:

KodProv: {Код проводника} INTEGER;

FioProv: {Фамилия проводника} STRING;

Таблица TVag:

Tvg: { тип вагона } INTEGER;

KolMest (Количество мест) : INTEGER;

В результате декомпозиции поучается следующая схема БД:

Этот вариант декомпозиции использовал правила приведения к 1 и 3 нФ, поскольку результаты полученные при приведении к 1 НФ, автоматически имели форму 2НФ.

Рассмотрим несколько другой вариант декомпозиции таблицы DetSved. Сворачивая поддерево, описывающее это отношение можно получить следующую таблицу Zvg, которая находится в 1NF:

KodRejs: (Номер рейса) : INTEGER;

NomNed {Номер недели} : INTEGER;

NomDen {номер дня недели}: INTEGER;