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

В программе реализовано 3 юнита.

Первый отвечает за формирование целостной структуры запроса.

Второй - за добавление и удаление таблиц из списка используемых для выборки данных, а также за изменение псевдонимов таблиц.

Третий – за назначение условий на поля таблиц.

Для хранения информации о таблицах в более удобном виде созданы следующие типы данных:

TAtrib = record

name,typ: string;

end;

TTables = record

name, psevdo : string;

atribs: array [0..10] of TAtrib;

end;

TArTables = array [0..10] of TTables;

Существует два массива Tables, UseTables: TArTables.

Массив Tables отвечает за хранение информации об имеющихся таблицах. Его инициализация происходит при создании формы.

В поле name нулевого элемента массива содержится информация о количестве таблиц. В поле name (нулевого элемента) вложенного массива атрибутов содержится информация о количестве атрибутов у данной таблицы. Это облегчает поиск данных в массиве.

Инициализация массива происходит в процедуре CreateTableList(var tables:TArTables), где сначала с помощью функции GetListTable (из модуля SysCat) получается список имен таблиц, разделенных символом #13. Они заполняются, потом определяется количество таблиц, а затем для каждой таблицы вызывается функция GetListAttr для получения имен атрибутов (имена которых также по спецификации модуля SysCat разделены символом #13) и GetTypeStr для получения типа атрибута.

Массив UseTables отвечает за используемые при построении результата таблицы, так как мы можем строить запрос лишь по одной таблице, или использовать в запросе одну и ту же таблицу с разными псевдонимами. Этот массив соответствует разделу from запроса. Его содержимое определяется во втором юните.

На главной форме создан список Listbox1, в котором отражаются имена и псевдонимы используемых таблиц. Чтобы добавить таблицу необходимо нажать на кнопку AddTable. При этом управление перейдет во второй модуль.

Рисунок 1 - Форма второго модуля

Здесь мы можем добавить таблицу в массив используемых. В выпадающем списке Combobox1 представлены имена всех доступных таблиц, которые получены из массива Tables, сформированного ранее. Можно указать псевдоним таблицы, однако это не обязательно.

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

При добавлении таблицы (то есть когда мы попали на вторую форму путем нажатия кнопки AddTable), кнопки изменения и удаления недоступны.

Эти функции становятся доступными в режиме редактирования, в который можно перейти, если дважды щелкнуть на названии таблицы в списке ListBox.

В этом режиме можно либо изменить псевдоним, либо удалить таблицу из списка используемых, поэтому выпадающий список всех таблиц заблокирован.

Реализовано две функции поиска таблиц: по имени (findTable_n) и по псевдониму (findTable_p), которые последовательно просматривают переданный массив и возвращают или 0, или индекс найденного элемента. При изменении, поиск таблицы сначала осуществляется по старому псевдониму (если такой был), а если псевдонима не было, то по имени (с условием равенства псевдонима пустой строке). Затем псевдоним заменятся на новый, а также заменяется везде, где это псевдоним (или имя) был использован.

При удалении таблицы из списка используемых производится поиск таблицы, а затем, все последующие элементы просто сдвигаются на один элемент назад, и после этого следует уменьшение количества таблиц в нулевом элементе массива.

Следует отметить, что в списке необходимо хранить только таблицы, действительно используемые при построении, иначе в разделе from появится еще одна таблица и результат будет некорректным.

Опишем главную форму (Рисунок 2).

На главной форме расположены 2 таблицы.

Верхняя - отвечает за первоначальной вывод сведений обо всех таблицах в памяти (из массива Tables). При этом дополнительно используются функции GetForeignKey и IsPrimaryKey из модуля SysCat для определения внешних и первичных ключей соответственно.

Рисунок 2 - Главная форма приложения

Собственно процесс построения запроса происходит во второй таблице.

Каждый столбец таблицы отвечает за одно поле какой-либо таблицы и условия, налагаемые на это поле. Предполагается, что на одно поле может быть наложено только одно условие из перечисленных в 1-ой части.

Каждая строка таблицы соответствует разделу запроса.

В первой строке таблицы указывается имя таблицы (from), во второй – имя поля, в третьей – тип сортировки (order by), в четвертой – вывод на результат (select), в пятой – условие (where).

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

В ячейках первых трех строк находятся выпадающие списки ComboBox.

Определен массив Combo: array [1..20,0..2] of TCombobox.

Его инициализация (создание объектов) происходит при создании формы. Каждому объекту передается область соответствующей ему ячейки, родителем назначается главная форма, а владельцем - StringGrid2.

Combo[i,j]:=TComboBox.Create(form1.StringGrid2);

Combo[i,j].BoundsRect := StringGrid2.CellRect(i,j);

Combo[i,j].Top:=combo[i,j].Top + StringGrid2.Top + 2;

Combo[i,j].Left:=combo[i,j].Left + StringGrid2.Left + 2;

Combo[i,j].Visible:=false;

Combo[i,j].Parent:=Form1;

Combo[i,j].Tag:=i;

Combo[i,j].OnChange:=form1.ComboBoxChange;

Процедуры обработки события OnChange всех объектов происходят в одной процедуре ComboBoxChange.

В неё передается параметр sender: TObject, в соответствии с которым определяются координаты объекта в массиве (и в таблице соответственно).

Изменение в объекте Combobox первой строки порождают изменения в содержимом Combobox того же столбца второй строки, то есть в выпадающем списке появляются имена атрибутов таблицы, выбранной выше.

Причем, если у таблицы был псевдоним, то в выпадающем списке будет представлен именно псевдоним, а не имя.

Рисунок 3. Выпадающий список в таблице.

Выпадающий список появляется только после выборы соответствующей ячейки и после выбора имени пропадает, а выбранное значение передается в ячейку Stringgrid, на области которой отображался ComboBox.

В третьей строке таблицы расположены элементы массива Combo, отвечающие за сортировку результирующего отношения и имеют по умолчанию 2 значения: “по возрастанию” и “по убыванию”.

Как и выпадающие списки первой строки, остальные также появляются при нажатии на ячейку и пропадают после выбора значения, передавая его в ячейку Stringgrid.

Элементами четвертой троки таблицы являются объекты типа TCheckBox, собранные в массиве Check: array [1..20] of TCheckBox;

Проставленная в соответствующем столбце галочка будет означать, что данный атрибут отношения, указанный в этом столбце, должен содержаться в результирующем отношении.

Последняя строка отвечает за условие, накладываемое на это поле. Само условие задается на 3-й форме (рисунок 4).

Рисунок 3 - Задание условия

На форме находятся 3 переключателя Radiobutton. Каждый из них соответствует одному типу условия. Значения с полей ввода и выпадающих списков считываются в зависимости от выбранного типа условия.

При работе с третьей формой, программа определяет тип атрибута, для которого задается условие.

Если этот тип – число, тогда при попытке сохранить условие на соответствие шаблону, программа выдаст сообщение о несоответствии типов. Необходимо отметить, что программа не содержит средств проверки синтаксической достоверности выражения после like. То есть правила, что % - любая последовательность символов и т.п. остаются на усмотрение пользователя.

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

При задании условия сравнения, пользователь выбирает знак (>,<,=, >=, <=) и тип значения, с которым будет сравнивать поле.

Этот тип задается в выпадающем списке с полями “поле” и “значение”.

На форме существуют 2 элемента в одном месте, поле ввода и выпадающий список.

Если для сравнения было выбрано "поле”, то поле ввода станет невидимым, а в выпадающем списке появятся все поля используемых отношений (в формате имя/псевдоним_таблицы . имя_атрибута), с которыми можно сравнить текущий атрибут, то есть все атрибуты, которые по типу соответствуют текущему, для этого просматривается весь массив UseTAbles.

Если для сравнения было выбрано "значение”, тогда видимым станет поле ввода, и введенное значение воспримется в зависимости от типа атрибута в апострофах или без них.

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

Достигается это следующим образом.

Существует лишь один экземпляр формы 3 для всех столбцов. Но определен тип записи, так называемый “образ формы”, который содержит всю необходимую информацию для того, чтобы восстановить исходный вид формы для соответствующего атрибута. Такой информацией является индекс выбранного RadioButton, а также содержание полей всех элементов (полей ввода и выпадающих списков).

TImageForm=record

IndexRadio:integer;

edit1,edit2,edit3,edit4:string;

combo1,combo2,combo3:string;

usl:string;

end;

frm:array[1..20] of TImageForm;

При нажатии кнопки “Оk” в соответствующий элемент массива заносятся текущие данные с формы, а при выборе ячейки таблицы отвечающей за условие, значения из “образа формы” передаются её полям.

Массив frm изначально инициализируется нулями.

В записи TImageForm предусмотрено поле usl, которое не относится непосредственно к внешнему виду формы. В нем хранится условие, которое задается данной формой.

Формирование этой строки происходит в соответствии с выбранным переключателем Radiobutton и составляется из служебных слов (таких как like и between) и значений полей ввода.