Создание программы средствами языка Delphi, реализующей системный каталог информации базы данных, его характеристики: отношения, атрибуты с типами, связи, индексы. Разработка подпрограмм для ввода таблиц, полей и ключей и приложения для вывода данных.
Аннотация к работе
Постановка задачи.
Список литературы
Приложение А (обязательное)- Листинг программы
Введение
Одной из функций СУБД является обеспечение функции системного каталога или словаря данных. Системный каталог - это набор таблиц и представлений, содержащих важную информацию о базе данных. Системный каталог имеется в любой базе данных. Информация в системном каталоге определяет структуру всей базы данных. Системный каталог фактически является частью базы данных. Системный каталог “содержит данные о данных” - метаданные, т.е. определения других объектов системы. Системный каталог может быть интегрирован в определяемую им базу данных, а значит, должен содержать описание самого себя.
Системный каталог в зависимости от реализации может делиться на логичные группы, чтобы обеспечить доступ к соответствующей информации не только администратору базы данных, но и другим заинтересованным пользователям. Например, пользователю может понадобиться информация о предоставленных ему привилегиях, но совсем не обязательно знать о внутренней структуре или внутренних процессах базы данных. Пользователь, как правило, обращается к системному каталогу за информацией о своих собственных объектах и привилегиях, а администратору базы данных может потребоваться информация о структуре любого объекта и информация о любом событии в базе данных. В некоторых реализациях в системном каталоге имеются такие объекты, которые оказываются доступными только для администратора базы данных.
Каталог состоит из таблиц. Их называют системными таблицами для отличия от обычных пользовательских. В результате пользователь может обращаться к каталогу так же, как к своим данным. Например, в каталоге обычно содержатся системные таблицы TABLES и COLUMNS, назначение которых - описание известных системе таблиц и столбцов этих таблиц.
Содержимое системного каталога может включать информацию по следующим разделам: · учетные записи пользователей и установки по умолчанию;
· привилегии и другая связанная с безопасностью информация;
· информация о других объектах базы данных, в частности, представлениях, синонимах, триггерах, сохраненных процедурах;
· ограничения для таблиц и информация о ссылочной целостности данных;
· пользовательские сеансы доступа;
· информация об аудитах;
· внутренние параметры базы данных;
· размещение файлов базы данных;
Системный каталог управляется сервером базы данных. При создании таблицы сервер базы данных вставляет данные об этом в соответствующую таблицу или представление каталога. При изменении пользователем структуры своей таблицы соответствующие объекты словаря данных тоже обновляются.
Таким образом, системный каталог является главным источником информации о структуре и природе базы данных. Он помогает содержать базу данных в порядке не только администратору базы данных и ее пользователям, но и серверу базы данных.
Целью данной работы является создание программы, реализующей системный каталог. Для достижения этой цели были поставлены следующие задачи: · написание подпрограмм, реализующих ввод таблиц, полей и ключей;
· создание приложения, позволяющего добавлять таблицы, поля и ключи, а также выводить данные из системного каталога;
1. Постановка задачи
Задача данной курсовой работы заключается в реализации системного каталога, основными хранимыми характеристиками которого являются отношения, атрибуты с типами, связи, индексы. Кроме того необходимо реализовать интерфейс для других работ, а именно для введения таблиц (отношений), полей таблиц, ключей (первичный и внешние).
Программа должна быть реализована средствами языка Delphi.
2. Описание решения
Содержимое каталога состоит из следующих файлов: файл таблиц, файл полей, файл ключей, файл индексов.
Файл таблиц - tables.txt, состоит из строк, в каждой из которых находится имя таблицы.
Файл полей - field.txt, состоит из строк, каждая из которых имеет следующий формат: |||
Файл ключей - keys.txt, состоит из строк, каждая из которых имеет структуру следующего вида: |||
При этом Внешний ключ состоит из пар вида: |
Файл индексов - index.txt, состоит из строк следующего вида: |||
Модуль MYFUNCTION содержит процедуры и функции необходимые для работы с системным каталогом. Процедуры ADDTABLE, ADDFIELD, ADDKEY, ADDINDEX осуществляют запись таблиц, полей, ключей и индексов в соответствующие файлы, на основании введенных пользователем данных. Процедура ADDTABLE реализована следующим образом.
procedure ADDTABLE(NAMETABLE: string);
begin
ASSIGNFILE(Tables,PATHTOTABLES);
append(Tables);
WRITELN(Tables,NAMETABLE);
CLOSEFILE(Tables);
end;
В качестве входного параметра выступает имя таблицы. Далее следует обращение к стандартным процедурам ASSIGNFILE и Append. ASSIGNFILE связывает файловую переменную с именем файла, Append - инициирует запись в существующий файл. Процедуры ADDFIELD, ADDINDEX реализованы анадогично.
Процедура ADDKEY позволяет вводить первичные ключи и внешние ключи, в зависимости от выбора режима пользователем. Переменная Logic типа boolean показывает, осуществлялись ли ранее записи в файл. Алгоритм этой процедуры представлен на рисунке 1.
Функции INTABLE, INFIELD, INKEY имеют выходное значение типа boolean. Они проверяют наличие соответствующего элемента во введенных данных.
Функции INTABLE в качестве параметра получает имя таблицы, наличие которой в файле Tables необходимо проверить. Далее выполняются процедуры открытия файла, считывается строка из файла и проверяется ее совпадение с входным параметром. В случае совпадения их значений функция принимает значение True, иначе - False.
Функция INFIELD имеет два параметра: имя таблицы NAMETABLE и имя поля NAMEFIELD. Данная функция работает следующим образом. Получаем стоку из файла Field. Вид этой строки таков, что сначала записано имя таблицы, а затем принадлежащее ей поле с указанием типа и его размера. Проверяем равенство входного параметра NAMETABLE и первых символов строки, содержащих имя поля, в случае равенства проверяем также соответствие параметра NAMEFIELD имени поля в данной строке файла. Таким образом просматриваем все строки файла. Функция принимает значение True в том случае если оба параметра совпали с информацией в строке файла.
Функция INKEY проверяет существования ключа у таблицы. Имеет 2 входных параметра: NAMETABLE и Why. Результат функции формируется следующим образом. В случае обнаружения в файле Keys записи соответствующей паре значений NAMETABLE и Why функция возвращает значение True, которое свидетельствует о наличии первичного либо внешнего ключа у таблицы. В противном случае возвращается значение False, что говорит об отсутствии ключа с данным именем у таблицы.
Эти функции используются для проверки корректности ввода данных пользователем.
Значения функций FSPISOKTABLES, FSPISOKFIELD, FSPISOKKEYS типа string содержат строку с содержимым соответствующего файла. Формат возвращаемого результата этих функций следующий: каждая строка файла отделена от последующей знаком &. Все эти функции реализованы аналогичным образом. Схема функций представлена на рисунке 2.
Функция FPRINTSTR возвращает содержимое каталога строкой. В этой строке последовательно представлена информация каталога по каждой таблице, разделенная знаком &. Алгоритм это функции представлен на рисунке 3.
Процедура PRINTDATA использует функцию FPRINTSTR и на основе ее результата выводит все поля заданной пользователем таблицы в текстовую таблицу STRINGGRID. Алгоритм работы этой процедуры можно записать следующим образом: 1. SPISOKPRINT:= FPRINTSTR;
2. Находим информацию в строке SPISOKPRINT о требуемой таблице;
3. Заносим имя требуемой таблицы в STRINGGRID;
Рисунок 1 - Алгоритм процедуры ADDKEY
Рисунок 2 - Схема функций FSPISOKTABLES, FSPISOKFIELD, FSPISOKKEYS
4. Находим информацию о ключах таблицы и заносим в STRINGGRID;
5. В переменную Column заносим имена всех полей и записываем в таблицу STRINGGRID;
6. В переменную COLUMNTYPE заносим типы полей и записываем в таблицу STRINGGRID;
Процедура PRINTTABLES выводит имена всех содержащихся в файле Tables.txt отношений и количество полей в каждом из них. Для реализации этой процедуры просматриваем строки файла Tables и выводим из в текстовую таблицу STRINGGRID.
Рисунок 3 - Алгоритм функции FPRINTSTR
Далее, просматривая строки файла Field считаем количество полей для каждой таблицы и эти значения также выводим в текстовую таблицу. PRINTRELATIONS - процедура, осуществляющая вывод в многострочное текстовое поле Memo информацию о связях между отношениями на основе содержимого файла Keys. Результат выполнения процедуры PRINTINDEX - вывод в STRINGGRID имени индекса и его принадлежность к полю и таблице. Работа данной процедуры основывается на просмотре информации файла Index.
3. Описание интерфейса приложения
Разработанное приложение имеет удобный интерфейс. На форме имеется меню, которое позволяет выбрать некоторое действие или выйти из программы. Пользователь может осуществлять следующие действия: · добавить таблицу
· добавить поле
· добавить ключ
· просмотреть каталог
В случае выбора пункта меню Добавить -> Таблицу на форме появляются однострочное текстовое поле для ввода имени таблицы и кнопка Добавить. При нажатии на нее информация о новой таблице будет занесена в файл.
При выборе пункта меню Добавить -> Поле пользователю, с помощью раскрывающегося списка, предлагается выбрать таблицу, в которое будет добавляться поле, ввести имя поля, выбрать его тип и длину типа. Состояние флага Индекс говорит о наличии или отсутствии индекса для данного поля таблицы. Пример работы приложения в таком состоянии представлена на рисунке 4.
Рисунок 4 - Пример работы приложения
Выбор пункта меню Добавить -> Ключ позволяет выбирать пользователю таблицу, куда требуется добавить ключ и его тип. В случае добавления первичного ключа, требуется ввести имя поля, которое будет однозначно идентифицировать запись таблицы. В случае выбора внешнего ключа пользователь заполняет два поля Foreign(туда записывается имя поля - внешний ключ) и References (содержит имя таблицы).
Пункт меню Просмотр каталога предоставляет пользователю выбор вида выводимой информации. С помощью переключателей можно выбрать режим вывода информации из системного каталога. Пример просмотра каталога представлены на рисунках 5, 6.
Рисунок 5 - Просмотр системного каталога
Рисунок 6 - Просмотр полей системного каталога
Заключение
В данной курсовой работе стояла цель реализовать системный каталог со следующими основными хранимыми характеристиками: отношения, атрибуты с типами, связи, индексы, а также реализовать интерфейс для выполнения других работ. В соответствии с поставленными задачами получены следующие результаты: · написаны подпрограммы, реализующие ввод таблиц, полей и ключей;
· написаны подпрограммы, создающие системный каталог;
· создано приложение, позволяющее добавлять таблицы, поля и ключи, а также выводить данные из системного каталога;
Поставленная в работе цель достигнута, все задачи выполнены полностью.
Список литературы
1. Швецов, В.И., Визгунов, А.Н., Мееров, И.Б. Базы данных [Текст]. - Учебное пособие. - Нижний Новгород: Издательство ННГУ, 2004.- 217 с.
2. Рыженков, Д.В. Курс лекций по дисциплине «Базы данных», 2009 г.
3. Дейт, К.Дж. Введение в системы баз данных, 6-е издание [Текст]: [пер. С англ.] /К.ДЖ. ДЕЙТ. - М. [и др.]: Вильямс, 2000. - 848 с.; 24 см. 4000 экз. - ISBN: 5-8459-0019-0. системный каталог ввод атрибут
MESSAGEDLG("Не все поля заполнены", MTERROR, [MBOK], 0);
if CHECKBOX1.Checked=true and (edit5.Text"")then begin
ADDINDEX(edit5.Text,COMBOBOX1.Text, Edit2.Text);
SHOWMESSAGE("Индекс добавлен");
end;
CLEARALL;
end else if (MYACTION=3) then begin
//Добавляем ключ if (Trim(COMBOBOX1.Text)"Выбрать") and (Trim(COMBOBOX2.Text)="Primary") then begin if (Trim(COMBOBOX1.Text)"Выбрать") and (Trim(Edit3.Text)"") then if not INKEY(Trim(COMBOBOX1.Text), "Primary") then if INFIELD(Trim(COMBOBOX1.Text), Trim(Edit3.Text)) then begin
MESSAGEDLG("Указанного поля не найдено в таблице " Trim(COMBOBOX1.Text), MTERROR, [MBOK], 0) else
MESSAGEDLG("Такой первичный ключ уже есть в таблице " Trim(COMBOBOX1.Text), MTERROR, [MBOK], 0) else
MESSAGEDLG("Не все поля заполнены", MTERROR, [MBOK], 0);
end else if (Trim(COMBOBOX2.Text)="Foreign") then begin if (Trim(COMBOBOX1.Text)"Выбрать") and (Trim(Edit3.Text)"") and (Trim(Edit4.Text)"") then begin if INFIELD(Trim(COMBOBOX1.Text), Trim(Edit3.Text)) then begin i:=1;
while i<=Length(Content) do begin if (Content[i]"|") then Temp:=Temp Content[i];
if (Content[i]="|") then begin if NAMETABLETEMP then SPISOKKEYS:=SPISOKKEYS Content "&" else if (Why="Primary") and (NAMETABLE=Temp) then begin SPISOKKEYS:=SPISOKKEYS NAMETABLE "|" Primary "|" Copy(Content,i 1,Length(Content)-i) "&"; Logic:=true; end else if (Why="Foreign") and (NAMETABLE=Temp) then begin SPISOKKEYS:=SPISOKKEYS Content "|" Foreign "|" References "&"; Logic:=true; end;
Temp:="";
i:=Length(Content);
end;
inc(i);
end;
end;
if not Logic then begin if Why="Primary" then
SPISOKKEYS:=SPISOKKEYS NAMETABLE "|" Primary "&" else if Why="Foreign" then
//Существование таблицы function INTABLE(NAMETABLE: string):boolean;
begin
Logic:=false;
ASSIGNFILE(Tables, PATHTOTABLES);
Reset(Tables);
Content:="";
while not eof(Tables) do begin
READLN(Tables, Temp);
if (NAMETABLE=Temp) then Logic:=true end;
CLOSEFILE(Tables);
INTABLE:=Logic;
end;
//Существование поля в таблице function INFIELD(NAMETABLE: string; NAMEFIELD: string):boolean;
var i, j, k, n, m: integer;
begin
ASSIGNFILE(Field, PATHTOFIELD);
k:=0;
m:=0;
n:=1;
Temp:="";
while n<=Length(NAMEFIELD) do begin if NAMEFIELD[n]"," then Temp:=Temp NAMEFIELD[n];
if (NAMEFIELD[n]=",") or (n=Length(NAMEFIELD)) then begin inc(m);
Temp:=NAMETABLE "|" Trim(Temp);
Reset(Field);
while not eof(Field) do begin
READLN(Field, Content);
i:=1;
j:=0;
Temp1:="";
while i<=Length(Content) do begin if (Content[i]"|") and (j2) then Temp1:=Temp1 Content[i] else if Content[i]="|" then begin Temp1:=Temp1 Content[i]; inc(j); end;
if (Content[i]="|") and (j=2) then begin if Temp1[Length(Temp1)]="|" then Temp1:=Copy(Temp1,1,Length(Temp1)-
1);
if Temp=Temp1 then inc(k);
Temp1:="";
i:=Length(Content);
end;
inc(i);
end;
end;
Temp:="";
CLOSEFILE(Field);
end;
inc(n);
end;
if m=k then Logic:=true else Logic:=false;
INFIELD:=Logic;
end;
//Существование ключа в таблице function INKEY(NAMETABLE: string; Why: string):boolean;
var i, j, n:integer;
begin
Logic:=false;
ASSIGNFILE(Keys, PATHTOKEYS);
reset(Keys);
SPISOKKEYS:="";
while (not eof(Keys)) and (not Logic) do begin
READLN(Keys, Content);
i:=1;
j:=0;
Temp:="";
while i<=Length(Content) do begin if Content[i]"|" then Temp:=Temp Content[i] else if Content[i]="|" then begin if (Temp=NAMETABLE) and (not Logic) then Logic:=true;
if Logic then inc(j);
end;
inc(i);
end;
end;
if (Logic) then begin if Why="Primary" then begin n:=j mod 2;
if n=1 then Logic:=true else Logic:=false;
end else if Why="Foreign" then begin if j>1 then Logic:=true else Logic:=false;
end end;
CLOSEFILE(Keys);
INKEY:=Logic;
end;
//Список таблиц function FSPISOKTABLES:string;
begin
ASSIGNFILE(Tables, PATHTOTABLES);
Reset(Tables);
SPISOKTABLES:="";
while not eof(Tables) do begin
READLN(Tables, Temp);
SPISOKTABLES:=SPISOKTABLES Temp "&";
end;
CLOSEFILE(Tables);
FSPISOKTABLES:=SPISOKTABLES;
end;
//Список полей function FSPISOKFIELD:string;
begin
ASSIGNFILE(Field, PATHTOFIELD);
reset(Field);
SPISOKFIELD:="";
while not eof(Field) do begin
READLN(Field, Temp);
SPISOKFIELD:=SPISOKFIELD Temp "&";
end;
CLOSEFILE(Field);
FSPISOKFIELD:=SPISOKFIELD;
end;
//Список ключей function FSPISOKKEYS:string;
begin
ASSIGNFILE(Keys, PATHTOKEYS);
Reset(Keys);
SPISOKKEYS:="";
while not eof(Keys) do begin
READLN(Keys, Temp);
SPISOKKEYS:=SPISOKKEYS Temp "&";
end;
CLOSEFILE(Keys);
FSPISOKKEYS:=SPISOKKEYS;
end;
function FPRINTSTR():string;
var i, j, k:integer;
begin
SPISOKTABLES:=FSPISOKTABLES;
i:=1;
Content:="";
SPISOKPRINT:="";
while i<=Length(SPISOKTABLES) do begin if SPISOKTABLES[i]"&" then Content:=Content SPISOKTABLES[i] else begin
SPISOKPRINT:=SPISOKPRINT Content;
Logic:=false;
SPISOKKEYS:=FSPISOKKEYS;
j:=1;
Temp:="";
while j<=Length(SPISOKKEYS) do begin if (SPISOKKEYS[j]"&") then Temp:=Temp SPISOKKEYS[j] else begin k:=0;
while k<=Length(Temp) do begin if Temp[k]="|" then begin if Content=Copy(Temp,1,k-1) then begin
" связана внешним ключом " foreign " с таблицей " NAMETABLE2 " ("
primary2 " - primary key)";
memo1.Lines.Add(s);
memo1.Lines.Add("");
s:="";
end;
end;
CLOSEFILE(keys);
end;
procedure PRINTINDEX(STRINGGRID1:TSTRINGGRID);
var i,n,rows:integer;
content:string;
begin
ASSIGNFILE(Index, PATHTOIND);
reset(Index);
rows:=1;
while not eof(index) do begin i:=1; n:=i;
readln(Index,Content);
while content[i]"|" do i:=i 1;
STRINGGRID1.Cells[0,rows]:= copy(content,n,i-n);
i:=i 1; n:=i;
while content[i]"|" do i:=i 1;
STRINGGRID1.Cells[1,rows]:= copy(content,n,i-n);
i:=i 1; n:=i;
while i<=length(content) do i:=i 1;
STRINGGRID1.Cells[2,rows]:= copy(content,n,i-n);
i:=i 1; n:=i;
rows:=rows 1;
end;
end;
//Изменение таблицы function ALTERTABLE(OLDNAME: string; NEWNAME: string):boolean;
var i:integer;
begin
Logic:=false;
ASSIGNFILE(Tables, PATHTOTABLES);
Reset(Tables);
Content:="";
while not eof(Tables) do begin
READLN(Tables, Temp);
if (OLDNAMETEMP) then Content:=Content Temp "|" else begin Content:=Content NEWNAME "|"; Logic:=true; end;
end;
CLOSEFILE(Tables);
Rewrite(Tables);
i:=1;
Temp:="";
while i<=Length(Content) do begin if Content[i]"|" then Temp:=Temp Content[i] else begin
WRITELN(Tables, Temp);
Temp:="";
end;
inc(i);
end;
CLOSEFILE(Tables);
//Изменяем в списке полей
ASSIGNFILE(Field, PATHTOFIELD);
Reset(Field);
SPISOKFIELD:="";
while not eof(Field) do begin
READLN(Field, Content);
i:=1;
Temp:="";
while i<=Length(Content) do begin if Content[i]"|" then Temp:=Temp Content[i] else begin if OLDNAMETEMP then SPISOKFIELD:=SPISOKFIELD Content "&" else SPISOKFIELD:=SPISOKFIELD NEWNAME Copy(Content, i, Length(Content)-i 1) "&";
Temp:="";
i:=Length(Content);
end;
inc(i);
end;
end;
CLOSEFILE(Field);
Rewrite(Field);
i:=1;
Temp:="";
while i<=Length(SPISOKFIELD) do begin if SPISOKFIELD[i]"&" then Temp:=Temp SPISOKFIELD[i] else begin
WRITELN(Field, Temp);
Temp:="";
end;
inc(i);
end;
CLOSEFILE(Field);
//Изменяем в списке ключей
ASSIGNFILE(Keys, PATHTOKEYS);
Reset(Keys);
SPISOKKEYS:="";
while not eof(Keys) do begin
READLN(Keys, Content);
i:=1;
Temp:="";
while i<=Length(Content) do begin if Content[i]"|" then Temp:=Temp Content[i] else begin if OLDNAMETEMP then SPISOKKEYS:=SPISOKKEYS Content "&" else SPISOKKEYS:=SPISOKKEYS NEWNAME Copy(Content, i, Length(Content)-i 1) "&";
Temp:="";
i:=Length(Content);
end;
inc(i);
end;
end;
CLOSEFILE(Keys);
Rewrite(Keys);
i:=1;
Temp:="";
while i<=Length(SPISOKKEYS) do begin if SPISOKKEYS[i]"&" then Temp:=Temp SPISOKKEYS[i] else begin