- •Базы данных
- •Содержание
- •Введение
- •1. Создание приложений с использованием технологии bde
- •1.1. Лабораторная работа № 1: создание базы данных
- •1.1.1. Создание таблиц dBase IV
- •1.1.2. Создание индексов
- •1.1.3. Создание таблиц Paradox 7
- •1.1.4. Задание свойств таблицы Paradox 7
- •Задание на лабораторную работу № 1
- •1.2. Лабораторная работа № 2: установление связей между таблицами в многотабличной базе данных
- •1.2.1. Создание алиаса
- •1.2.2. Связывание таблиц
- •Задание на лабораторную работу № 2
- •1.3. Лабораторная работа № 3: работа с полями и компонентом dbGrid
- •1.3.1. Использование объектов-полей
- •1.3.2. Обращение к значению поля
- •1.3.3. События объекта-поля
- •1 Рис. 10. Пример использования события OnCellClick .3.4. События сетки dbGrid
- •1.3.5. Создание объектов-столбцов в dbGrid
- •1.3.6. Формирование списка возможных значений столбца
- •Задание на лабораторную работу № 3:
- •1.4. Лабораторная работа № 4: работа с наборами данных (компонент Table)
- •1.4.1. Открытие и закрытие набора данных
- •1.4.2. Доступ к записям
- •1.4.3. Навигация по набору данных
- •1.4.4. Поиск записей в наборах данных
- •1.4.5. Реализация каскадных изменений
- •1.4.6. Пример выполнения лабораторной работы
- •Задание на лабораторную работу № 4
- •1.5. Лабораторная работа № 5: работа с отчетами
- •1.5.1. Создание простейшего отчета
- •1.5.2. Создание отчета для связанных наборов данных
- •1.5.3. Использование выражений (компонент qrExpr)
- •1.5.4. Группирование данных в отчете
- •Задание на лабораторную работу № 5:
- •1.6. Лабораторная работа № 6: sql-запросы (компонент Query)
- •Задание на лабораторную работу № 6
- •2. Создание приложений, работающих с базами данных interbase
- •2.1. Лабораторная работа № 1: создание схемы базы данных
- •2.2. Лабораторная работа № 2: доступ к базе данных InterBase c использованием dbExpress
- •2.3. Лабораторная работа № 3: транзакции
- •2.4. Лабораторная работа № 4: отображение данных запроса
- •2.5. Лабораторная работа № 5: вычисляемые, агрегатные и подстановочные поля
- •2.5.1. Вычисляемые поля
- •2.5.2. Агрегатные поля
- •2.5.3. Подстановочные поля
- •2.6. Лабораторная работа № 6: связь Master-Detail
- •2.7. Лабораторная работа № 7: локальная репликация данных
- •Приложение 1 варианты заданий к лабораторным работам Вариант 1. Прием заказов
- •Вариант 2. Поставки товаров
- •Вариант 3. Исполнители
- •Вариант 4. Картинная галерея
- •Вариант 5. Порт
- •Вариант 6. Студенты
- •Вариант 7. Строительная компания
- •Вариант 8. Автосалон
- •Вариант 9. Аэропорт
- •Вариант 10. Диагностический центр
- •Вариант 11. Реклама
- •Вариант 12. Быстрая пицца
- •Вариант 13. Клуб собаководов
- •Вариант 14. Грузоперевозки
- •Вариант 15. Аптека
- •Вариант 16. Автовокзал
- •Вариант 17. Общественная организация
- •Вариант 18. Учет потребления газа
- •Приложение 2 порядок выполнения лабораторных работ
- •Библиографический список
1.4.6. Пример выполнения лабораторной работы
Организация поиска
Допустим, у нас имеются четыре таблицы (см. прил. 1, вар. 3). На форме необходимо разместить 4 компонента Table, 4 DataSource и 4 DBGrid и связать их между собой (процедура связывания таблиц описана в лаб. работе № 2). Для выбора таблицы, в которой будет проводиться поиск, и поля поиска нам потребуется компонент ComboBox (способы работы с ним см. в [1]). Главное окно программы может выглядеть, например, так (рис. 14):
Рис. 14. Пример организации интерфейса приложения
Задача поиска сводится к следующему. Если нам нужно найти запись в выбранной нами таблице и вывести всю информацию, связанную с этой записью, из других таблиц, то необходимо:
установить связи между таблицами так, чтобы главной стала выбранная таблица;
задать в главной таблице условие фильтрации по тому значению поля, которое мы ищем.
Рассмотрим установление связей. Пусть, например, пользователь выбрал в ComboBox1 таблицу RECORDS, т.е. Table4. Чтобы для каждой записи можно было найти ее исполнителя, альбом, в который она входит, и стиль музыки, требуется сделать таблицу Table4 главной. Для этого вначале устраним существующие связи между таблицами (эту операцию удобно описать в отдельной процедуре):
Table1.MasterFields:='';
Table1.MasterSource:=nil;
Эти действия необходимо выполнить для каждой из четырех таблиц.
Далее, установим связи между таблицами так, чтобы для Table1 и Table2 главной стала таблица Table3, а для Table3 — таблица Table4.
Свойствам IndexName подчиненных таблиц, имеющих более одного индекса, присваиваются имена соответствующих индексов (их можно узнать в окне Object Inspector, просмотрев значения свойства IndexName требуемой таблицы). Например, если в таблице Table3 (ALBUMS) определены 3 индекса:
ID_ALBUM (индекс по коду альбома);
ID_ARTIST (по коду исполнителя);
ID_STYLE (по коду стиля),
то при связывании ее с таблицей Table1 (ARTISTS) нужно установить Table3.IndexName:=’ID_ARTIST’, а при связывании с Table2 (STYLES) устанавливается Table3.IndexName:=’ID_STYLE’, и т.д.
Внимание: для таблиц Paradox имя индекса нужно устанавливать только в том случае, если индекс вторичный. Иначе свойству IndexName присваивается пустая строка.
В последнюю очередь свойствам MasterFields присваиваются имена полей главных таблиц, по которым они связываются с подчиненными.
Итак:
Table1.MasterSource:=DataSource3;
Table1.MasterFields:='ID_ARTIST';
Table2.MasterSource:=DataSource3;
Table2.MasterFields:='ID_STYLE';
Table3.IndexName:='ID_ALBUM';
Table3.MasterSource:=DataSource4;
Table3.MasterFields:='ID_ALBUM';
Чтобы сформировать в ComboBox2 список полей таблицы Table4, очистим его и добавим в него все имеющиеся в Table4 имена полей:
ComboBox2.Clear;
for i:=0 to Table4.FieldDefs.Count-1 do
ComboBox2.Items.Add(Table4.FieldDefs.Items[i].Name);
В итоге, событие OnChange компонента ComboBox1 будет выглядеть так:
procedure TForm1.ComboBox1Change(Sender: TObject);
var
i: byte;
begin
// разрываем связи между таблицами
Table1.MasterFields:='';
Table1.MasterSource:=nil;
Table2.MasterFields:='';
Table2.MasterSource:=nil;
Table3.MasterFields:='';
Table3.MasterSource:=nil;
Table4.MasterFields:='';
Table4.MasterSource:=nil;
ComboBox2.Clear;
case ComboBox1.ItemIndex of
3: begin // выбрана таблица Table4
// делаем Table4 главной
Table1.IndexName:='ID_ARTIST';
Table1.MasterSource:=DataSource3;
Table1.MasterFields:='ID_ARTIST';
Table2.IndexName:='ID_STYLE';
Table2.MasterSource:=DataSource3;
Table2.MasterFields:='ID_STYLE';
Table3.IndexName:='ID_ALBUM';
Table3.MasterSource:=DataSource4;
Table3.MasterFields:='ID_ALBUM';
// заполняем ComboBox2 именами полей таблицы Table4
for i:=0 to Table4.FieldDefs.Count-1 do
СomboBox2.Items.Add(Table4.FieldDefs.Items[i].Name);
end;
0: begin // выбрана таблица Table1
// выполняем аналогичные действия для Table1
end;
1: begin // выбрана таблица Table2
// выполняем аналогичные действия для Table2
end;
2: begin // выбрана таблица Table3
// выполняем аналогичные действия для Table3
end;
end;
end;
Теперь опишем событие, которое произойдет, когда пользователь нажмет на кнопку «Поиск». В этом случае для выбранной пользователем таблицы нужно установить критерий фильтрации по выбранному полю. Событие будет выглядеть так (Edit1 — поле ввода значения, которое ищет пользователь):
procedure TForm1.Button1Click(Sender: TObject);
var
FilterString: String;
begin
FilterString:=ComboBox2.Text + '=''' + Edit1.Text + '''';
case ComboBox1.ItemIndex of
0: begin
Table1.Filter:=FilterString;
Table1.Filtered:=True;
end;
1: // аналогичные действия для Table2
2: // аналогичные действия для Table3
3: // аналогичные действия для Table4
end;
end;
В результате, как только пользователь нажмет на кнопку «Поиск», во всех таблицах должны появиться записи, соответствующие найденной записи в главной таблице.
Работа с формами
Часто на главной форме не хватает места для новых компонентов, или число их слишком велико для восприятия. В таких случаях используются дополнительные формы, которые невидимы до тех пор, пока не потребуется их отобразить.
Для создания нового окна в программе выберите в меню File->New->Form. Появится новая форма. При запуске программы она не будет видна, но во время разработки вы ее видите и можете размещать на ней компоненты. Для переключения между формами используйте клавиши Shift-F12.
Чтобы вызвать вторую форму (т.е. сделать ее видимой и активной), надо использовать метод ShowModal. Например, при нажатии кнопки «Добавить запись» на первой форме нужно, чтобы появилась вторая (рис. 15).
Это делается так:
procedure TForm1.Button1Click(Sender: TObject);
begin
Form2.Showmodal;
end;
Можно использовать и метод Show вместо ShowModal, но особенность последнего в том, что нельзя переключиться на другие окна программы, пока не будет закрыта форма, метод которой вызвали.
Если нужно из второй формы (Form2) обратиться к объектам первой формы (Form1), то надо это явно указать. Например, при нажатии кнопки на второй форме требуется изменить надпись на кнопке первой формы:
procedure TForm2.Button1Click(Sender: TObject);
begin
Form1.Button1.Caption:=’Новое имя’;
end;
Добавляя «Form1» перед интересующим нас объектом, мы и указываем, что действия надо проводить с объектом на первой форме.
Когда работа со второй формой завершена, ее надо закрыть. Это делает метод Close:
procedure TForm2.Button1Click(Sender: TObject);
begin
//Здесь выполняется все, что требуется
Close; // а здесь мы закрываем форму и возвращаемся
// на форму, откуда вызывали…
end;
Рис. 15. Использование дополнительной формы
Для ввода пользователем значений полей новой записи или полей изменяемой записи можно использовать компоненты Edit. Помните, что редактироваться будет запись, выбранная в таблице в настоящий момент.
В приведенном выше примере на второй форме находятся компоненты для изменения данных во всех четырех таблицах, причем таблицы, в которых необходимо вставить или изменить данные, пользователь отмечает «галочками» — компонент CheckBox. В этом компоненте есть свойство Checked, которое равно True, если «галочка» установлена, и False в противном случае. Компонент находится на закладке Standard.
Кроме того, рекомендуется использовать компонент DBLookupComboBox для установки значений тех полей, которые ссылаются на данные в справочных таблицах (рис. 16). Особенности работы с этим компонентом описаны ниже.
Рис. 16. Использование компонента DBLookupComboBox
Использование компонента DBLookupComboBox
Компонент DBLookupComboBox находится на закладке Data Controls (рис. 17). Он предназначен для формирования выпадающего списка значений на основе полей одной из таблиц БД.
Рис. 17. Компонент DBLookupComboBox
Для того чтобы получить полный набор этих значений, можно добавить дополнительный компонент Table, не связанный с другими таблицами, и DataSource для него. Свойства компонента DBLookupComboBox настраиваются так:
ListSource — это объект DataSource, связанный со справочной таблицей, по данным которой формируется выпадающий список;
ListField — поле таблицы, значения которого отображаются в списке. Эти значения будет видеть пользователь;
KeyField — поле таблицы, значение которого компонент возвращает при выборе пользователем одного из элементов списка.
Чтобы получить значение ключа выбранного элемента программно, нужно обратиться к свойству KeyValue. Оно имеет тип Variant; это означает, что вам может потребоваться преобразование типа перед использованием значения этого свойства:
var id: string;
...
id:=DBLookupComboBox1.KeyValue; // здесь тип Variant преобра-
// зуется к типу String
Table1.InsertRecord([Edit1.Text, id, Edit2.Text])
Необходимо отметить, что компонент DBLookupComboBox можно напрямую связать с таблицей, данные которой требуется изменить. Для этого в свойстве DataSource устанавливается источник данных редактируемой таблицы, а в DataField — ее поле. Тогда при выборе одного из элементов списка в это поле будет записано значение ключевого поля, указанного в KeyField.