48632 (608696), страница 2
Текст из файла (страница 2)
Рисунок 3.1 – Связи между таблицами БД «График учета рабочего времени на шахте им. Т. Кузембаева в цехе «Автоматика» »
4. Нормализация отношений
Нормальная форма — требование, предъявляемое к структуре таблиц в теории реляционных баз данных для устранения из базы избыточных функциональных зависимостей между атрибутами (полями таблиц). Процесс преобразования базы данных к виду, отвечающему нормальным формам, называется нормализацией.
Каждая нормальная форма представляет собой определённое условие, которому должна соответствовать таблица базы данных. Если таблица не соответствует нормальной форме, она может быть приведена к ней (нормализована) за счёт декомпозиции, то есть разбиения на несколько таблиц, связанных между собой. Теоретически, в результате нормализации объём БД должен уменьшиться. Принципиальным здесь является то, что нормализация — обратимый процесс, из группы таблиц, получившихся при декомпозиции, всегда можно получить в точности исходную таблицу. Таким образом, нормализация не сокращает объём информации, хранимой в БД, а лишь устраняет информацию, которая может быть вычислена.
Типы нормальных форм. Нормализация может применяться к таблице, первоначально отвечающей следующим требованиям:
-
Таблица содержит нуль или более записей.
-
Все записи таблицы имеют одно и то же множество полей, причём одноимённые поля относятся к одинаковым типам данных.
-
Таблица не может содержать двух полностью идентичных записей.
Обычно выделяют шесть нормальных форм:
Первая нормальная форма (1NF). Таблица находится в первой нормальной форме, если каждый её атрибут атомарен и все строки различны. Под выражением "атрибут атомарен" понимается, что атрибут может содержать только одно значение. Таким образом, не соответствуют 1NF таблицы, в полях которых могут храниться списки значений. Для приведения таблицы к 1NF обычно требуется разбить таблицу на несколько отдельных таблиц.
Вторая нормальная форма (2NF). Таблица находится во второй нормальной форме, если она находится в первой нормальной форме, и при этом любой её атрибут, не входящий в состав первичного ключа, функционально полно зависит от первичного ключа. Функционально полная зависимость означает, что атрибут функционально зависит от всего первичного ключа, но при этом не находится в функциональной зависимости от какой-либо его части.
Третья нормальная форма (3NF). Таблица находится в третьей нормальной форме, если она находится во второй нормальной форме, и при этом любой её неключевой атрибут функционально зависит только от первичного ключа.
Нормальная форма Бойса-Кодда (BCNF)Таблица находится в BCNF, если она находится в третьей нормальной форме, и при этом отсутствуют функциональные зависимости атрибутов первичного ключа от неключевых атрибутов. Данная нормальная форма — это модификация третьей нормальной формы. Таблица может находиться в 3NF, но не в BCNF, только в одном случае: если она имеет, помимо первичного ключа, ещё по крайней мере один составной возможный ключ, и по крайней мере один из атрибутов таблицы входит и в первичный, и в возможный ключи. Такое бывает достаточно редко, в остальном 3NF и BCNF эквивалентны.
Четвёртая нормальная форма (4NF).Таблица находится в 4NF, если она находится в BCNF и не содержит нетривиальных многозначных зависимостей. Многозначная зависимость не является функциональной, она существует в том случае, когда из факта, что в таблице содержится некоторая строка X, следует, что в таблице обязательно существует некоторая определённая строка Y.
Пятая нормальная форма (5NF).Таблица находится в 5NF, если она находится в 4NF и любая многозначная зависимость соединения в ней является тривиальной.
Основываясь на концептуальной модели, создаем следующие сущности: Рабочие, Праздники, Отпуска, Статус, Выходные, Профессия, Сохраненные графики, Месяцы, Графики, Типы дней.
Сущность «Сохраненные_графики» имеет следующие атрибуты:
ID, NameGraphic, DateOfSave, LinkMonthNum, YearNum.
Сущность «Рабочие» имеет следующие атрибуты: ID, WokerName, TabNumber, LinkProfession, LinkStatus.
Сущность «Выходные» имеет атрибуты: ID, DateCelebrate, LinkName.
Таким образом в данной базе данных отношения находятся в третьей нормальной форме, т.к. все записи атомарные, значения одного атрибута одного и того же типа, порядок следования атрибутов в таблице не существенен, во всех отношениях первичный ключ состоит из одного атрибута, в отношениях нет транзитивных зависимостей.
5. Основная часть
На данной блок схеме представлен общий алгоритм составления графика учета рабочего времени. Для более детального изучения алгоритма можно посмотреть приложение Б в котором помещен исходный код с подробными комментариями. При запуске приложение проверяет, существует ли файл базы данных, если он не найден, происходит динамическое создание структуры базы данных с заполнением первоначальных значений в поля.
6. SQL запросы
Для базы данных «График учета рабочего времени на шахте им. Т. Кузембаева в цехе «Автоматика» » выполнены следующие запросы:
-
Подсчет количества записей в таблице
Function SQL_CountRows(table:string;Connection:TADOConnection):integer;
var
str:_Recordset;
request:string;
begin
request := 'SELECT COUNT(ID) FROM ' + table;
STR := Connection.Execute(request);
result := integer(str.Fields.Item[0].Value);
end;
где table – передаваемый в функцию параметр – название таблицы;
-
Получение значений атрибутов из таблицы «Отпуски», для заполнения массива, хранящего эти значения для последующих вычислений.
request := 'SELECT LinkWoker, DateBegin, Length FROM ОТПУСКИ';
STR := ADOConnection1.Execute(request);
-
Получение значений атрибутов из таблицы «Рабочие», для заполнения массива, хранящего эти значения для последующих вычислений
request := 'SELECT WokerName, LinkStatus, TabNumber FROM РАБОЧИЕ';
STR := ADOConnection1.Execute(request);
-
Пометка выходных дней в массиве дней месяца из таблицы, в которой хранятся данные о выходных днях «Выходные».
with sql_CreateQuery(ADOConnection1) do begin
SQL.Text := 'SELECT DateCelebrate FROM Выходные WHERE DateCelebrate BETWEEN :Date1 and :Date2';
with Parameters do begin
ParseSQL(SQL.Text, true);
ParamValues['Date1'] := Date1;
ParamValues['Date2'] := Date2;
end;
Open;
while not(EOF) do begin
MonthInfo[DayOfTheMonth(TDateTime(FieldValues['DateCelebrate']))] := DayCelebrate;
next;
end;
Close;
Free;
end;
-
Сохранение названия сохраненного графика, даты сохранения в таблицу «Сохраненные_графики».
procedure SaveToSavedGraphic(NameBD:string; DateOfSave:TDateTime; MonthNum, YearNum:integer);
begin
with sql_CreateQuery(ADOConnection1) do begin
SQL.Text := 'INSERT INTO Сохраненные_графики (NameGraphic, DateOfSave, LinkMonthNum, YearNum) VALUES(:p1, :p2, :p3, :p4)';
with parameters do begin
ParseSQL(SQL.Text, true);
ParamValues['p1'] := NameBD;
ParamValues['p2'] := DateOfSave;
ParamValues['p3'] := MonthNum;
ParamValues['p4'] := YearNum;
end;
ExecSQL();
Close;
Free;
end;
end;
-
Процедура сохранения самого графика в таблицу «Графики», с указанием ID сохранения в таблице «Сохраненные_графики».
procedure SaveToGraphic(IDNum, LinkWoker, LinkTypeOfDay:integer; DateOfCell:TDateTime);
begin
with sql_CreateQuery(ADOConnection1) do begin
SQL.Text := 'INSERT INTO Графики (LinkSaveId, LinkWoker, LinkTypeOfDay, DateOfCell) VALUES(:p1, :p2, :p3, :p4)';
with parameters do begin
ParseSQL(SQL.Text, true);
ParamValues['p1'] := IDNum;
ParamValues['p2'] := LinkWoker + 1;
ParamValues['p3'] := LinkTypeOfDay;
ParamValues['p4'] := DateOfCell;
end;
ExecSQL();
Close;
Free;
end;
-
Получение ID последней добавленной в таблицу строки.
function GetLastID(conn:TADOConnection):integer;
begin
result := 0;
with sql_CreateQuery(conn) do begin
SQL.Text := 'SELECT @@IDENTITY';
Open();
if Not (eof) then begin
result := Fields.Fields[0].Value;
end;
Close();
Free;
end;
end;
request := 'CREATE TABLE Профессия ' + '( ' +
ID IDENTITY (1, 1) CONSTRAINT PK_Profession_ID PRIMARY KEY, '+
nameProfession CHAR(255) NOT NULL UNIQUE '+ ')';
Conn.Execute(request);
request := 'CREATE TABLE Статус ' + '( ' +
' ID IDENTITY (1, 1) CONSTRAINT PK_Profession_ID PRIMARY KEY, ' +
nameStatus CHAR(255) NOT NULL UNIQUE '+ ')';
Conn.Execute(request);
request := 'CREATE TABLE Рабочие ' +'( ' +
' ID IDENTITY (1, 1) CONSTRAINT PK_Woker_ID PRIMARY KEY, ' +
' WokerName CHAR(128) NOT NULL , ' +
' TabNumber INTEGER , ' +
' LinkProfession INTEGER not null CONSTRAINT LINK_Profession_ID ' +
' REFERENCES Профессия(ID) , ' +
' LinkStatus INTEGER not null CONSTRAINT LINK_Status_ID ' +
' REFERENCES Статус(ID)' + ')';
Conn.Execute(request);
request := 'CREATE TABLE Отпуски ' + '( ' +
' ID IDENTITY (1, 1) CONSTRAINT PK_Holidays_ID PRIMARY KEY , ' +
' LinkWoker INTEGER not null CONSTRAINT LINK_Woker_ID ' +
' REFERENCES Рабочие(ID) , ' +
' DateBegin Date , ' +
' Length INTEGER ' + ')';
Conn.Execute(request);
request := 'CREATE TABLE Типы_дней ' + '( ' +
' ID INTEGER UNIQUE, ' +
' NameOfType CHAR(128) ' + ')';
Conn.Execute(request);
request := 'CREATE TABLE Месяцы ' + '( ' +
' ID INTEGER UNIQUE, ' +
' MonthName CHAR(128) ' + ')';
Conn.Execute(request);
request := 'CREATE TABLE Сохраненные_графики ' + '( ' +
' ID IDENTITY (1, 1) CONSTRAINT PK_SavedGraphic_ID PRIMARY KEY , ' +
' NameGraphic CHAR(128) , ' +
' DateOfSave DATE , ' +
' LinkMonthNum INTEGER not null CONSTRAINT LINK_Month_ID ' +
' REFERENCES Месяцы(ID) , ' +
' YearNum CHAR(128) ' + ')';
Conn.Execute(request);
request := 'CREATE TABLE Графики ' + '( ' +
' ID IDENTITY (1, 1) CONSTRAINT PK_Graphic_ID PRIMARY KEY, ' +
' LinkSaveID INTEGER not null CONSTRAINT LINK_SavedGraphics_ID ' +
' REFERENCES Сохраненные_графики(ID) , ' +
' DateOfCell DATE , ' +
' LinkWoker INTEGER not null CONSTRAINT LINK_Woker_IDN ' +
' REFERENCES Рабочие(ID) , ' +
' LinkTypeOfDay INTEGER not null CONSTRAINT LINK_TypeOfDay_ID ' +
' REFERENCES Типы_дней(ID) ' + ')';
Conn.Execute(request);
request := 'CREATE TABLE Праздники ' + '( ' +
' ID IDENTITY (1, 1) CONSTRAINT PK_Celebrate_ID PRIMARY KEY , ' +
' Title CHAR(128) ' + ')';
Conn.Execute(request);
request := 'CREATE TABLE Выходные ' + '( ' +
' ID IDENTITY (1, 1) CONSTRAINT PK_DateCelebrate_ID PRIMARY KEY , ' +
' DateCelebrate DATE , ' +
' LinkName INTEGER not null CONSTRAINT LINK_HOL_ID' +
' REFERENCES Праздники(ID) ' + ')';
Conn.Execute(request);
//---------------------------------Заполнение полей значениями------------------
request := 'INSERT INTO Месяцы(ID, MonthName)'+
' VALUES (0, ''Январь '')';
Conn.Execute(request);
request := 'INSERT INTO Месяцы(ID, MonthName)'+
' VALUES (1, ''Февраль '')';
Conn.Execute(request);
request := 'INSERT INTO Месяцы(ID, MonthName)'+
' VALUES (2, ''Март '')' ;
Conn.Execute(request);
request := 'INSERT INTO Месяцы(ID, MonthName)'+
' VALUES (3, ''Апрель '')';
Conn.Execute(request);
request := 'INSERT INTO Месяцы(ID, MonthName)'+
' VALUES (4, ''Май '')';
Conn.Execute(request);
request := 'INSERT INTO Месяцы(ID, MonthName)'+
' VALUES (5, ''Июнь '')';
Conn.Execute(request);
request := 'INSERT INTO Месяцы(ID, MonthName)'+
' VALUES (6, ''Июль '')';
Conn.Execute(request);
request := 'INSERT INTO Месяцы(ID, MonthName)'+
' VALUES (7, ''Август '')';
Conn.Execute(request);
request := 'INSERT INTO Месяцы(ID, MonthName)'+
' VALUES (8, ''Сентябрь '')';
Conn.Execute(request);
request := 'INSERT INTO Месяцы(ID, MonthName)'+
' VALUES (9, ''Октябрь '')';
Conn.Execute(request);
request := 'INSERT INTO Месяцы(ID, MonthName)'+
' VALUES (10, ''Ноябрь '')';
Conn.Execute(request);
request := 'INSERT INTO Месяцы(ID, MonthName)'+
' VALUES (11, ''Декабрь '')';
Conn.Execute(request);