Лабораторная работа №13
Связи между таблицами в приложении Delphi
С.В. Каверин
Цель работы: Ознакомится с возможностью связывания двух наборов данных (НД) с помощью свойств MasterSource/MasterFields, с возможностью расширения таблиц до НД за счет добавочных Lookup-полей, организация спрятанных (невидимых пользователю) полей.
Набор данных (НД) – это совокупность записей, взятых из одной или нескольких таблиц БД. НД является логической таблицей.
Постановка задачи. Окончательный вид окна просмотра товаров и заказов, приведен на рисунке 1. На нем изображены два набора данных.
[pic]
Рисунок 1 – Вид окна «Связанные таблицы»
Первый набор – это таблица «Товары», у которой невидимыми являются поля КодПоставки, Описание и Изображение. Второй набор данных «Заказы» – это подчиненная таблица «Заказы» с добавленными полями ФИО, Адрес и Телефон из таблицы «Клиенты» и полями Фамилия, Имя из таблицы «Сотрудники». В этом НД поля КодСотрудника и КодТовара из «Таблицы «Заказы» являются невидимыми. При выборе записи главной таблицы «Товары» во второй таблице (НД Заказы) выводятся только те данные, которые соответствуют выбранной записи из первой таблицы.
Порядок выполнения работы:
Создаем новую рабочую форму приложения (Form4). В меню главной формы (Form1) создаем закладку вызова Form4.
Создаем две новые таблицы ADOTable1 и ADOTable2, связываем их с таблицами «Товары» и «Заказы».
Производим связывание таблиц ADOTable1 и ADOTable2 с помощью свойств MasterSource/MasterFields и выводим их на экран формы Form4 с помощью сеток DBGrid1 и DBGrid2.
Расширяем таблицу ADOTable2 до набора данных «Заказы», путем формального (не физического) дополнения новых полей из таблиц «Клиенты» и «Сотрудники». Делаем невидимыми кодовые поля (их пользователю видеть не обязательно).
Запрещаем редактирование таблиц на Form4.
1 Создание нового окна «Связанные таблицы»
1.1 Создаем Form4 (File -> New-> Form-Delphi), сохраняем как Unit4.
1.2 Устанавливаем свойство Form4.Caption = Связанные таблицы.
1.3 Знакомим Form4 с Form1 и DatMod (с помощью File->Use Unit..).
1.4 Переходим на Form1. В меню приложения добавляем новую закладку Связанные таблицы. Для этого дважды кликаем на компонент MainMenu1 и в окне создания меню выбираем нужные места (выставляя курсор) и в соответствующие свойстве Caption пишем нужные заголовки пунктов (см. рисунок 2).
[pic]
Рисунок 2 – Настройка компонента MainMenu1
1.5 Дважды кликаем по пункту меню Товары из вкладки Связанные_таблицы (см. рисунок 2). В обработчике событий пишем код:
[pic]
1.6 Сохраняем проект (File -> Save All) и компилируем (F9).
2 Установка отношений между таблицами БД
Таблица TabZakaz (Заказы) является подчиненной по отношению к главной таблице TabTovar (Товары), т.к. в БД между соответствующими таблицами есть связь «один (от главной таблице) ко многим (к подчиненной таблице)» (см. рисунок 3).
[pic]
Рисунок 3 – Структура БД «Товар»
Сразу оговоримся, что если мы сделаем связывание таблиц TabZakaz и TabTovar с помощью свойств MasterSource/MasterFields, то это повлечёт изменение вывода этих таблиц на Form2. А это не входит в наши планы, т.к. Form2 предназначена для редактирования таблиц целиком. Поэтому создаем новые таблицы ADOTable1 и ADOTable2, которые дублируют таблицы Товары и Заказы из БД.
2.1 Переходим на модуль данных dm. Положите на dm два компонента ADOTable (закладка dbGo) и два DataSource (закладка DataAccess).
2.2 Подключим таблицу ADOTable1 к компоненту ADOConnection1 и к главной таблице «Товары» нашей БД «Товар».
В инспекторе объектов таблицы ADOTable1 устанавливаем свойства:
2.3 В инспекторе объектов компонента DataSource1 установите свойство DataSet = ADOTable1.
2.4 Проведя аналогичные действия (п.2.2 и п.2.3) подключите таблицу ADOTable2 и DataSource2 к компоненту ADOConnection1 и к подчиненной таблице «Заказы» нашей БД.
2.5 Двойным щелчком на компоненте ADOTable1 откроем Окно редактора полей, щелкнем в окне правой кнопкой мыши и в контекстном меню выберем команду Add all fields.
2.6 Переходим на Form4 и оформляем вывод таблиц на дисплей. Возьмите два компонента GroupBox (закладка Standard), используя свойства Caption дайте им заголовки «Товары» (для GroupBox1) и «Заказы» (для GroupBox2).
2.7 Положите в GroupBox1 сетку DbGrid1 (закладка Data Controls). Для DbGrid1 свяжите свойство DataSource с источником данных DataSource1. Если данные не отобразились, то в Окне редактора полей (двойной клик по DbGrid1) выберите команду Add all fields.
2.8 Проводим связывание таблиц. Переходим на модуль данных dm. В Инспекторе объектов подчиненной таблицы ADOTable2 устанавливаем свойство MasterSource = DataSource1 (источник главной таблицы).
2.9 Обращаемся к свойству MasterFillds. В появившемся окне Редактора полей (см. рисунок 4) выберите ключевое поле КодТовара главной таблицы (окно Master Filds) и поле КодТовара подчиненной таблицы (окно Detail Filds). Нажмите кнопку Add, а затем «OK». Связь установлена.
[pic]
Рисунок 4 – Установка связи между таблицами ADOTable1 и ADOTable2
2.10 Сохраняем проект (File -> Save All), компилируем и запускаем проект (F9 или Run). Окно формы показано на рисунке 5. Обратите внимание на эффект от связывания таблиц. Сравните с выводом этих данных в окне
«Заказы» «Товары» «Клиенты» (Form2).
[pic]
Рисунок 5 – Окно закладки «Связанные таблицы»
3 Добавление подстановочных полей НД «Заказы»
Внимание! Организовать другие два отношения для подчиненной таблицы ADOTable2 (ADOTable2->TabKlient и ADOTable2->TabSotrydniki) с помощью свойств MasterSource/MasterFields не удастся (можно создать только одну такую связь). Решить проблему дополнения полей НД «Заказы» можно с помощью подстановочных полей (Lookup fields). Они имитируют реальные поля, выполняя подстановку значений из других таблиц (по ключам).
3.1 Организуем Lookup-поле «ФИО_Клиента» в таблице ADOTable2, связанное с полем ФИО таблицы TabKlient.
3.1.1 Переходим на модуль dm. Выделяем ADOTable2.
3.1.2 В Инспекторе объектов таблицы ADOTable2 устанавливаем свойство Active = False – перед созданием новых полей необходимо закрыть компонент.
3.1.3 Двойным щелчком на компоненте ADOTable2 откройте окно редактора полей и щелчком правой кнопки мыши вызовете контекстное Меню. Выберете команду New Field, чтобы открыть окно конструктора нового поля (рисунок 6).
[pic]
Рисунок 6 – Окно конструктора нового поля «ФиоКлиент»
В окне конструктора нового поля заполняем:
Элементы группы Field properties:
Name = ФиоКлиент – имя нового поля.
Component = ADOTable2Field (устанавливается автоматически).
Type = String – тип нового поля (как в БД).
Size = 50 (как размер поля ФИО в таблице Клиенты).
Элементы группы Field type:
Элементы группы Lookup definition:
Key fields = КодКлиента – внешний ключ в нашем наборе данных (таблице Заказы).
DataSet = TabKlient – дополнительный НД (таблица Клиенты).
Lookup keys = Код – ключевое поле дополнительного НД.
Result field = ФИО – поле дополнительного НД, которое будет отображаться в поле ФиоКлиент нашего НД (таблице Заказы).
3.1.4 В Инспекторе объектов таблицы ADOTable2 установите свойство Active = Try.
3.1.5 Сохраните проект (File->Save All), скомпилируйте и запустите (F9).
3.2 Организуйте Lookup-поле «АдресКлиент» в таблице ADOTable2, связанное с полем Адрес таблицы TabKlient (см. рисунок 7).
3.3 Организуйте Lookup-поле «ТелефонКлиент» в таблице ADOTable2, связанное с полем Телефон таблицы TabKlient (тип – string, размер 15).
3.4 Организуйте Lookup-поле «ФамилияСотрудника» в таблице ADOTable2, связанное с полем Фамилия таблицы TabSotrydniki (тип – string, размер 50).
[pic]
Рисунок 7 – Окно конструктора нового поля «АдресКлиент»
3.5 Организуйте Lookup-поле «ИмяСотрудника» в таблице ADOTable2, связанное с полем Имя таблицы TabSotrydniki (тип – string, размер 50).
4 Сделаем невидимыми кодовые поля таблиц на Form4, т.к. их не обязательно видеть пользователю. Установим запрет на редактирование.
4.1 Переходим на Form4. Дважды щелкните мышью на сетке DBGrid1, вызовется редактор столбцов (рисунок 8) и, если необходимо, выберете команду Add All Fields. Далее редактируем свойства каждого столбца в отдельности.
4.2 Редактируем поле КодТовара. В инспекторе объектов для DBGrid1.Columns[0] устанавливаем свойства: Alignment=taCenter (по центру), Visible=Try (изображать на сетке).
[pic]
Рисунок 8 – Настройка столбцов сетки DBGrid1
4.2 В редакторе столбцов DBGrid1 последовательно выберайте столбцы КодПоставки, Описание и Изображение, и выставляйте свойство: Visible=False (не изображать на сетке).
4.3 Для НД «Заказы» (сетка DBGrid2) сделайте невидимыми поля КодЗаказа, КодСотрудника, КодТовара, КодКлиента.
4.4 Сохраните проект (File->Save All), скомпилируйте и запустите (F9).
4.5 Сделаем запрет на редактирование сеток DBGrid1 и DBGrid2. Для этого в Инспекторе раскрываем вкладку Option (нажимаем +) и устанавливаем свойство dgEditing=False.
[pic]
4.6 Сохраните проект (File->Save All), скомпилируйте и запустите (F9).
5. Проблема. При изменении записей в таблицах «Заказы», «Товары», «Клиенты» на форме Form2, не происходит обновления в таблицах связанных наборов данных «Товары» и «Заказы» на форме Form4.
!!! Изменения в таблицах наступают по нажатию кнопки [pic] (nbRefresh – обновить) на компоненте DBNavigator.
5.1 Обновление НД «Товары» на форме Form4.
5.1.1 Переходим на Form2. Заходим в Инспектор объектов DBNavigator2. Вызываем обработчик события OnClick (двойным кликом).
5.1.2 В открывшемся окне Code пишем код обновления таблицы ADOTable1, которая связана с НД «Товары» на форме Form4.
[pic]
Пояснение. Если на DBNavigator2 нажата кнопка [pic] nbRefresh, то дополнительно (свойство Requery) обновляется таблица ADOTable1.
5.2 Обновление НД «Заказы» на форме Form4, который связан с таблицами «Заказы», «Клиенты» и «Сотрудники».
5.2.1 Изменение таблицы «Заказы» на форме Form2.
[pic]
5.2.2 Изменение таблицы «Клиенты» на форме Form2.
[pic]
5.2.3 Аналогично, произведите изменение таблицы «Сотрудники» на форме Form3.
5.3 Сохраните проект (File->Save All), скомпилируйте и запустите (F9).
6 Задания для самостоятельной работы
Усовершенствуйте проект своего варианта, введя в него просмотр связанных наборов данных, по аналогии с разработкой Form4 проекта «Информационная система Товар».
Литература
Фленов М.Е. Библия Delphi //СПб.: БХВ-Петербург.-2011.-688с.