Компонент TDataSource
Компонент DataSource действует как посредник между компонентами TDataSet (TTable, TQuery, TStoredProc) и компонентами Data Controls - элементами управления, обеспечивающими представление данных на форме. Компоненты TDataSet управляют связями с библиотекой Borland Database Engine (BDE), а компонент DataSource управляет связями с данными в компонентах Data Controls.
В типичных приложениях БД компонент DataSource, как правило, связан с одним компоненом TDataSet (TTable или TQuery) и с одним или более компонентами Data Controls (такими, как DBGrid, DBEdit и др.). Связь этого компонента с компонентами TDataSet и DataControls осуществляется с использованием следующих свойств и событий:
Cвойство DataSet компонента DataSource идентифицирует имя компонента TDataSet. Можно присвоить значение свойству DataSet на этапе выполнения или с помощью инспектора объектов на этапе проектирования. Cвойство Enabled компонента DataSource активизирует или останавливает взаимосвязь между компонентами TDataSource и Data Controls. Если значение свойства Enabled равно true, то компоненты Data Controls, связанные с TDataSource, воспринимают изменения набора данных. Использование свойства Enabled позволяет временно разъединять визуальные компоненты Data Controls и TDataSource, например, для того, чтобы в случае поиска в таблице с большим количеством записей не отображать на экране пролистывание всей таблицы. Свойство AutoEdit компонента DataSource контролирует, как инициируется редактирование в компонентах Data Controls. Если значение свойства AutoEdit равно true, то режим редактирования начинается непосредственно при получении фокуса компонентом Data Controls, связанным с данным компонентом TDataSet. В противном случае режим редактирования начинается, когда вызывается метод Edit компонента TDataSet, например, после нажатия пользователем кнопки Edit на компоненте DBNavigator. · Событие OnDataChange компонента DataSource наступает, когда происходит изменение значения поля, записи, таблицы, запроса. Cобытие OnUpdateData компонента DataSource наступает, когда пользователь пытается изменить текущую запись в TDataSet. Обработчик этого события следует создавать, когда требуется соблюсти условия ссылочной целостности или ограничения, накладываемые на значения полей изменяемой базы данных.
| |
Компонент TDBGrid
Компонент TDBGrid обеспечивает табличный способ отображения на экране строк данных из компонентов TTable или TQuery. Приложение может использовать TDBGrid для отображения, вставки, уничтожения, редактирования данных БД. Обычно DBGrid используется в сочетании с DBNavigator, хотя можно использовать и другие интерфейсные элементы, включив в их обработчики событий методы First, Last, Next, Ptior, Insert, Delete, Edit, Append, Post, Cancel компонента TTable.
Внешний вид таблицы (например, надписи в заголовках столбцов) может быть изменен с помощью редактора свойств Columns Editor. Для вызова Columns Editor нужно либо выбрать соответствующую опцию в контекстном меню компонента DBGrid или щелкнуть мышью в колонке значений напротив свойства Columns в инспекторе объектов.
Рис. 4. Установка свойств столбцов DBGrid с помощью Columns Editor
Вторым способом получения контроля над характеристиками DBGrid или другими компонентами является создание описанным выше способом статического набора компонентов TField. Имея компонент типа TField, созданный для каждого из полей в наборе данных, можно установить ширину, формат, маску, расположение, метку для отображения в DBGrid и другие характеристики.
Поля Float, Integer и Date обладают свойством DisplayMask. Это свойство можно использовать, чтобы форматировать данные в компоненте DBGrid или другом компоненте Data Controls. Например, экранный формат mm-dd-yy может использоваться для размещения полей типа дата.
Некоторые компоненты TField (например, TStringField) обладают свойством EditMask, которое можно установить, вводя данные в DBGrid и другие компоненты Data Controls. Для установки свойства EditMask нужно установить компонент Field в Object Inspector и выбрать свойство EditMask, после чего появится диалоговая панель Input Mask Editor, представленная на рис. 5. Чтобы проверить маску редактирования, нужно ввести значение в поле Test Input.
Рис. 5. Диалоговая панель Input Mask Editor
| |
Компонент TField
Объекты класса TField являются свойством объекта TDataSet (напомним, что некоторые свойства объектов сами являются объектами с их собственными наборами свойств, и TField - один из них).
Свойство Fields объекта типа TDataSet позволяет обращаться к отдельным полям набора данных. Свойство Fields является массивом или набором объектов TField, динамически создающимся во время выполнения приложения. Элементы массива соответствуют колонкам таблицы.
Объект TField не делает никаких предположений относительно типов данных, с которыми он связан. Он имеет несколько свойств, позволяющих установить или вернуть обратно значения поля, например, AsString, AsBoolean, AsFloat, AsInteger. Наиболее часто используются свойства Text (cтрока текста, выводимого в связанный с данным полем интерфейсный элемент) и FieldName (имя поля базы данных).
Fields Editor позволяет создать так называемый статический список полей таблицы, добавляемых к описанию класса формы. Когда впервые используются такие компоненты TDataSet, как компонент TTable или TQuery, список полей для них динамически генерируется в процессе выполнения приложения на основе имеющихся столбцов таблиц или результатов SQL-запроса. Fields Editor позволяет определить и затем модифицировать статический список компонентов Field на этапе проектирования приложения. При внесении колонок с использованием Fields Editor для каждого из полей, добавленных к TDataSet, возникают объекты TField, после чего можно увидеть эти поля в инспекторе объектов и использовать в приложениях их свойства, события и методы.
Использовать Fields Editor нужно следующим образом:
Разместить компонент TTable или TQuery на форме. Установить свойство DatabaseName для TTable или TQuery. Установить свойство TableName компонента TTable или свойство SQL компонента TQuery. Выбрать компонент TDataSet на форме и нажать правую клавишу мыши, после чего появится контекстное меню. Из контекстного меню выбрать Fields Еditor. Появится пустое окно с заголовком, совпадающим с именем компонента TTable. Снова нажать правую клавишу мыши над пустым окном и из контекстного меню выб ать опцию Add Fields.
Имена всех колонок таблицы или запроса появятся в диалоговой панели Add Fields (рис. 1.)
Рис.1. Формирование списка полей
Выбрать поля, которые нужно внести в список объектов, и нажать OK.
Рис. 2. Сформированный список полей, доступных на этапе проектирования
Если требуется создать вычисляемое поле на основе имеющихся полей, нажать правую клавишу мыши и из контекстного меню выбрать New Field для создания нового поля на основе существующего или для создания вычисляемого поля (в дальнейшем следует создать код обработчика события OnCalcFields компонента TTable, где и производятся необходимые вычисления). Если необходимо удалить статическое поле из списка полей в наборе данных, нужно нажать правую клавишу мыши и из контекстного меню выбрать Delete.
После того, как в Fields Editor добавлены поля, они появятся в инспекторе объектов, а ссылки на них - в h-файле формы.
Если теперь применить операцию drag-and-drop к выделенным в Fields Editor полям, перенеся их на форму, то можно получить готовую форму с необходимым набором интерфейсных элементов (в нашем случае - DBEdit, позволяющий отображать и редактировать строковые, числовые, денежные и другие поля, чьи значения представимы в виде строки символов, и DBImage, позволяющий отображать графические поля и использовать Clipboard для их редактирования). Если к такой форме добавить компонент TDBNavigator (этот компонент реализует основные методы TTable и TQuery, связанные с редактированием данных) и связать его с имеющимся компонентом TDataSource, а затем скомпилировать проект, получим приложение для просмотра и редактирования данных в таблице.
Рис. 3. Результат переноса на форму полей из Fields Editor
При работе Fields Editor создаются объекты, соответствующие видимым в инспекторе объектов полям. Эти объекты являются потомками объектного типа TField. Таблица 1 описывает существующие классы таких объектов:
Таблица 1. Потомки TField
TStringField | Текстовые данные фиксированной длины до 8192 символов. |
TAutoIncField | Целые числа от -2,147,483,648 до 2,147,483,647. Предназначен для нумерации ст ок в наборе данных. Потомок TIntegerField. |
TIntegerField | Целые числа от -2,147,483,648 до 2,147,483,647. |
TSmallIntField | Целые числа от -32768 до 32767. |
TWordField | Целые числа от 0 до 65535. |
TFloatField | Действительные числа с абсолютной величиной от 1.2x10e-324 до 1.7x10e308 с точностью до 15-16 цифры. |
TCurrencyField | Действительные числа с абсолютной величиной от 1.2x10e-324 до 1.7x10e308 с точностью до 15-16 цифры. |
TBooleanField | Значения true или false. |
TDateTimeField | Значения даты и времени. |
TDateField | Значения даты. |
TTimeField | Значения времени. |
TBlobField | Произвольное поле данных без ограничений размера. |
TBytesField | Произвольное поле данных без ограничений размера. |
TVarBytesField | Произвольное поле данных до 65535 символов с фактической длиной, представленной в первых двух байтах. |
TMemoField | Текст произвольной длины. |
TGraphicField | Графическое поле произвольной длины, например, битовый массив. |
Компонент TQuery
Компонент TQuery, как и компонент TTable, обладает всеми свойствами компонента TDataSet.
Как и в случае с компонентом TTable, компонент TDataSource управляет взаимодействием между компонентами Data Controls и компонентом TQuery. Обычно приложение имеет один компонент DataSource для каждого компонента TQuery.
Наиболее часто используются следующие свойства компонента TQuery:
Active - указывает, открыт (true) или закрыт (false) данный запрос Eof, Bof - эти свойства принимают значение true, когда указатель текущей записи расположен на последней или соответственно первой строке набора данных, являющегося результатом выполнения запроса. DatabaseName - имя каталога либо псевдоним (alias) удаленной БД, к которой осуществляется запрос. DataSource - указывает источник данных для параметризованных запросов (т.е. запросов с параметрами, значение которых заранее неизвестно). Fields - это свойство доступно только во время выполнения (run-time only) и используется для чтения или модификации поля, определяемого по порядковому номеру. Params - содержит параметры для параметризованного запроса, как SomeNo в следующем примере:
Select * from Orders where CustNo=:SomeNo
SQL - строковый массив, содержащий текст оператора запроса SQL.
Отметим, что язык запросов SQL (Structured Query Language), традиционно применяемый при работе с серверными СУБД, может быть использован и при работе с таблицами формата dBase и Paradox. Не вдаваясь в подробное описание синтаксиса этого языка (с ним можно познакомиться в других источниках, например, в книге М.Грабера "Введение в SQL"), отметим одну его особенность. SQL – язык непроцедурный. На нем можно написать, что нужно получить в результате запроса, но нельзя написать, как это сделать, то есть нельзя описать саму процедуру выполнения запроса. Дело в том, что реализация выполнения тех или иных операторов SQL серверами баз данных может быть различна, и в большинстве случаев неинтересна клиентскому приложению, создаваемому с помощью С++ Builder. В случае таблиц dBase или Paradox реализацию SQL берет на себя библиотека Borland Database Engine.
Компонент TQuery позволяет использовать операторы SQL для того, чтобы определять или создавать наборы данных, которые можно отобразить на экране, вставлять, удалять и редактировать строки.
RequestLive - если это свойство имеет значение true и синтаксис запроса таков, что его результат может быть модифицируем, пользователь может редактировать данные с сохранением их в базе данных. Если RequestLive имеет значение false, результат запроса возвращается в состоянии read-only.
Наиболее часто используются следующие методы компонента TQuery:
ExecSQL - выполняет SQL-запрос, содержащийся в свойстве SQL, если запрос не возвращает данные. Следует употреблять этот метод при вставке, редактировании или удалении данных. При выполнении же оператора SELECT (выбор данных) следует использовать метод Open. Следующий пример показывает применение метода ExecSQL:
Query1->Close(); Query1->SQL->Clear(); Query1->SQL->Add("Delete emp where empno=1010"); Query1->ExecSQL();
Open - открывает компонент TQuery. Он эквивалентен присвоению свойству Active значения true. Используется, если результатом запроса является набор данных (такие запросы обычно начинаются с оператора SELECT). Пример использования метода Open:
Query1->Open();
Close - закрывает компонент TQuery. Вызов Close эквивалентен присвоению свойству Active значения false. Пример использования метода Close:
Query1->Close();
Prepare - обеспечивает передачу серверу баз данных запроса, содержащегося в свойстве SQL, для оптимизации и компиляции. Полный запрос с параметрами не передается, пока не вызваны методы Open или ExecSQL. Даже если метод Prepare не вызывается явно, он будет вызван неявно, если используются методы Open или ExecSQL (в этом можно убедиться, запустив утилиту SQL Monitor). Пример использования метода Prepare:
Query1->Close(); Query1->SQL->Add("Delete emp where empno=:empno"); Query1->Prepare();
Компоненты TQuery обладают большим разнообразием методов, унаследованных от TDataSet. Наиболее часто используются следующие методы: First, Last, Next, Prior перемещают указатель текущей записи на первую, последнюю, следующую и предыдущую записи соответственно, например: MoveBy перемещает указатель на определенное количество строк. Insert, Edit, Delete, Append, Post, Cancel - позволяют модифицировать результат запроса. Метод Insert позволяет вносить в результат запроса строки, как в следующем примере:
Query2->Insert(); Query2->Fields[0]->AsInteger = 100; Query2->Fields[1]->AsString =Edit1->Text; Query2->Post();
Метод Post подтвержает операции Insert, Update или Delete, совершая реальное физическое изменение в базе данных. Метод Cancel отменяет незавершенные операции Insert, Delete, Edit или Append. FreeBookmark, GetBookmark, GotoBookmark- - позволяют создавать закладки (маркированные строки) в запросе и затем вернуться к такой строке позже.
Прежде чем перейти к непосредственному использованию запросов, следует остановиться на весьма полезном инструменте - генераторе запросов Visual Query Builder, с помощью которого можно определить свойство SQL компонента TQuery, если по каким-либо причинам это неудобно делать непосредственно в редакторе свойств.
| |
Компонент TTable
Наиболее простым способом обращения к таблицам баз данных является использование компонента TTable, предоставляющего доступ к одной таблице. Для этой цели наиболее часто используются следующие свойства:
Active - указывает, открыта (true) или нет (false) данная таблица. DatabaseName - имя каталога, содержащего искомую таблицу, либо псевдоним (alias) удаленной БД (псевдонимы устанавливаются с помощью утилиты конфигурации BDE, описание которой присутствует во многих источниках, посвященных продуктам Borland, либо с помощью SQL Explorer, вызываемого с помощью пункта меню Database/Explore). Это свойство может быть изменено только в случае, если таблица закрыта (ее свойство Active равно false), например:
Table1->Active = false; Table1->DatabaseName = "BCDEMOS" Table1->Active = true;
TableName - имя таблицы. Exclusive - если это свойство принимает значение true, то никакой другой пользователь не может открыть таблицу, если она открыта данным приложением. Если это свойство равно false (значение по умолчанию), то другие пользователи могут открывать эту таблицу. IndexName - идентифицирует вторичный индекс для таблицы. Это свойство нельзя изменить, пока таблица открыта. MasterFields - определяет имя поля для создания связи с другой таблицей. MasterSource - имя компонента TDataSource, с помощью которого TTable будет получать данные из связанной таблицы. ReadOnly - если это свойство равно true, таблица открыта в режиме "только для чтения". Нельзя изменить свойство ReadOnly, пока таблица открыта. Eof, Bof - эти свойства принимают значение true, когда указатель текущей записи расположен на последней или соответственно первой записи таблицы. Fields - массив объектов TField. Используя это свойство, можно обращаться к полям по номеру, что удобно, когда заранее неизвестна структура таблицы:
Edit1->Text=Table1->Fields[2]->AsString;
Наиболее часто при работе с компонентом TTable используются следующие методы:
Open и Close устанавливают значения свойства Active равными True и False соответственно. Refresh позволяет заново считать набор данных из БД. First, Last, Next, Prior перемещают указатель текущей записи на первую, последнюю, следующую и предыдущую записи соответственно, например:
Table1->First(); while (!Table1->Eof) { //что-то делаем... Table1->Next(); };
MoveBy перемещает указатель на указанное число строк (оно может быть и отрицательным) в пределах таблицы Insert, Edit, Delete, Append - переводят таблицу в режимы вставки записи, редактирования, удаления, добавления записи соответственно. Post - осуществляет физическое сохранение измененных данных. Например:
Table2->Insert(); Table2->Fields[0]->AsInteger = 100; Table2->Fields[1]->AsString =Edit1->Text; Table2->Post();
Cancel - отменяет внесенные изменения, не сохраненные физически. FieldByName - предоставляет возможность обращения к данным в полях по имени поля:
S=Table1->FieldByName("area")->AsString;
SetKey переключает таблицу в режим поиска. GotoKey начинает поиск строки, значение Fields[n] которой равно выбранному, где n - номер колонки таблицы, начиная с 0:
Table1->SetKey(); Table1->Fields[0]->AsString=Edit1->Text; Table1->GotoKey();
SetRangeStart, SetRangeEnd, ApplyRange позволяют выбрать нужные строки на основе диапазона значений какого-либо поля.
Table1->SetRangeStart(); Table1->Fields[0]->AsString = Edit1->Text; Table1->SetRangeEnd(); Table1->Fields[0]->AsString = Edit2->Text; Table1->ApplyRange();
FreeBookmark, GetBookmark, GotoBookmark- позволяют создать помеченную строку в таблице и затем вернуться к ней позже. Методы Bookmark используют класс TBookmark. Метод GetBookmark устанавливает закладку на текущей cтроке таблицы. GotoBookmark осуществляет перемещение в таблице к строке, ранее отмеченной закладкой. Метод FreeBookmark используется для уничтожения объекта типа TBookmark:
TBookmark Marker =Table1->GetBookmark(); Table1->GotoBookmark(Marker); Table1->FreeBookmark(Marker);
Cобытия компонента TTable позволяют строить и контролировать поведение приложе ий БД. Например, событие BeforePost наступает перед вставкой или изменением записи, событие AfterPost - после сохранения вставленной или измененной записи, событие AfterDelete - после удаления записи и т.д.
Чтобы внести компонент TTable в форму, нужно выполнить следующее:
Используя страницу Data Access палитры компонентов, разместить компонент TTable на форме или в модуле данных. Свойству DatabaseName присвоить имя каталога, где находится БД, либо псевдо има БД. Свойству TableName присвоить имя таблицы или выбрать таблицу из выпадающего списка. Внести в форму компонент DataSource и установить значение свойства DataSet равным имени компонента TTable. Внести компоненты Data Controls и связать их с компонентом DataSource для того, чтобы отобразить на экране данные из таблицы БД.
| |
Компоненты TDBLookup
Компоненты DBLookup используются при наличии связанных таблиц, когда необходимо вывести на экран описательную информацию вместо поля, содержащего ее код.
C++ Builder предоставляет четыре компонента для просмотра и ввода значений в таблицы:
Компонент TDBLookupListBox (страница Data Controls) Компонент TDBLookupComboBox(страница Data Controls) Компонент TDBLookupList (страница Win 3.1) Компонент TDBLookupCombo(страница Win 3.1)
Последние два компонента присутствуют в палитре компонентов с целью совместимости с формами, созданными в версии Delphi 1.0 (как известно, в C++ Builder можно использовать формы Delphi 1.0 и 2.0).
Компоненты DBLookupList и DBLookupListBox являются похожими на ListBox компонентами, созданными для просмотра значения в одной таблице, основанного на значении в другой таблице. DBLookupList и DBLookupListBox содержат конечный набор значений. Когда DBLookupList и DBLookupListBox используются для ввода данных, пользователь должен выбрать один вариант из списка. DBLookupList и DBLookupListBox позволяют вывести на экран набор вариантов, основанных на значении в другой таблице.
Компоненты DBLookupList и DBLookupListBox отличаются от компонента DBListBox тем, что позволяют согласовать выбранное значение из списка с текущей строкой другой таблицы БД, тогда как для DBListBox список значений для выбора определен заранее и не имеет отношения к таблицам БД.
Компоненты DBLookupCombo и DBLookupComboBox являются похожими на ComboBox компонентами, то есть они похожи на DBLookupList и DBLookupListBox, за исключением того, что пользователь может либо выбирать значение в списке, либо вводить новое значение. ComboBox, на который похожи DBLookupCombo и DBLookupComboBox, сочетает в себе возможности ListBox с возможностями компонента Edit. DBLookupCombo и DBLookupComboBox отличаются от компонента ComboBox тем, что позволяют согласовать выбранное значение с текущей строкой другой таблицы БД. При размещении компонентов DBLookupList, DBLookupListBox, DBLookupCombo или DBLookupComboBox на форме эта форма в приложении должна содержать DataSource и компонент - потомок TDataSet (например, TTable).
| |
Модули данных
В предыдущем примере мы размещали компоненты со страницы Data Access непосредственно на главную форму приложения. Однако наличие на форме большого количества невидимых компонентов в ряде случаев затрудняет проектирование пользовательского интерфейса. Кроме того, нередко бывает удобно отделить компоненты, отвечающие за доступ к данным и бизнес-логику информационной системы, от интерфейсных элементов, например, для обегчения ее дальнейшей модернизации. Для этой цели в C++ Builder имеется специальный тип, называемый модулем данных - TDataModule. Компонент этого типа можно условно считать специальным видом формы, хотя он и порожден непосредственно от TСomponent. Такой компонент-контейнер может содержать компоненты со страницы Data Access, а сам он не виден пользователю во время выполнения.
Создадим другую версию рассмотренного выше примера с использованием модуля данных. В этом случае компоненты Data Access помещаются в модуль данных, а ссылка на соответствующий h-файл помещается в модуль, связанный с главной формой приложения.
Рис.14. Размещение компонентов доступа к данным в DataModule
Приведем исходный текст модуля, связанного с главной формой новой версии приложения:
//---------------------------------------------------- #include <vcl\vcl.h> #pragma hdrstop
#include "cust1.h" #include "custdm1.h" // Ссылка на модуль данных //----------------------------------------------------- #pragma link "Grids" #pragma resource "*.dfm" TForm1 *Form1; //----------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner): TForm(Owner) { } //----------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { if (DataModule1->Table1->Active) { DataModule1->Table1->Close(); Button1->Caption = "Открыть таблицу &клиентов"; } else { DataModule1->Table1->Open(); Button1->Caption= "Закрыть таблицу &клиентов"; }; } //----------------------------------------------------- void __fastcall TForm1::Button2Click(TObject *Sender) { if (DataModule1->Query1->Active) { DataModule1->Query1->Active = false; Button2->Caption = "Открыть таблицу &заказов";} else
{ DataModule1->Query1->Active = true; Button2->Caption = " Закрыть таблицу &заказов"; } } //----------------------------------------------------- void __fastcall TForm1::RadioButton1Click(TObject *Sender) { DBGrid1->DataSource = DataModule1->DataSource1; } //----------------------------------------------------- void __fastcall TForm1::RadioButton2Click(TObject *Sender) { DBGrid1->DataSource = DataModule1->DataSource2; } //----------------------------------------------------- void __fastcall TForm1::RadioButton3Click(TObject *Sender) { DBGrid1->DataSource = DataModule1->DataSource3; } //---------------------------------------------------- void __fastcall TForm1::Button3Click(TObject *Sender) { if (DataModule1->Table1->Active) { DataModule1->Table1->SetRangeStart(); DataModule1->Table1->Fields[0]->AsString = Edit1->Text; DataModule1->Table1->SetRangeEnd(); DataModule1->Table1->Fields[0]->AsString = Edit2->Text; DataModule1->Table1->ApplyRange(); } } //----------------------------------------------------
| |
Разработка простейшего приложения
Попробуем создать простейшее приложение для редактирования таблицы БД. Для этого воспользуемся таблицей COUNTRY базы данных BCDEMOS, содержащейся в комплекте поставки C++ Builder.
Создадим новый проект и сохраним его главную форму как COUNT1.CPP, а сам проект как COUNT.MAK. Используя страницу Data Access палитры компонентов, разместим компоненты TTable и DataSource на форме. Установим свойство Database Name компонента Table1 равным BCDEMOS, свойство TableName равным COUNTRY.DB, а свойство Active равным true. Далее установим значение свойства DataSet компонента DataSource1 равным Table1.
Используя страницу Data Controls палитры компонентов, внесем компоненты DBGrid и DBNavigator в форму. Присвоим свойству DataSource обоих компонентов значение DataSource1.
Рис. 6. Главная форма приложения COUNT
Полученный проект можно скомпилировать и протестировать.
Отметим, что есть и более простой способ построить подобное приложение. Для этой цели можно воспользоваться утилитой SQL Explorer, вызываемой с помощью пункта меню Database/Explore. Выбрав страницу Databases в левой части окна SQL Explorer и щелкнув на значке "+" возле имени соответствующей базы данных, нужно выбрать опцию Tables. Затем в правой части окна нужно выбрать закладку Summary и перетащить с помощью мыши значок с именем нужной таблицы (в нашем случае COUNTRY.DB) на пустую форму. На форме появятся компоненты TDBGrid, TDataSource и TTable. После этого следует добавить DBNavigator, связать его с TDataSource и сделать таблицу активной.
Рис. 7. SQL Explorer
| |
Разработка приложения, использующего вычисляемое поле
Таблица, используемая в предыдущем примере, содержит поля Area (площадь в кв.км ) и Population (население). Попробуем создать вычисляемое поле, содержащее п отность населения стран, представленных в этой таблице. Для этого запустим Fields Editor для компонента Table1, внесем все поля этой таблицы в набор данных и создадим новое поле с названием pop2. Выберем Float в списке Field type. Убедимся, что выбрана радиокнопка Calculated, и щелкнем на кнопке OK
Рис. 8. Создание вычисляемого поля
Создадим обработчик события OnCalcFields компонента Table:
Table1pop2->Value=Table1Population->Value/Table1Area->Value;
Установим значение свойства DisplayFormat компонента Table1Pop2 равным .## . Запустим и протестируем приложение и убедимся в том, что вычисляемое поле действительно присутствует.
| |
Разработка приложения, использующего компонент просмотра баз данных
В этом примере рассматривается связь таблиц CUSTOMER (компании-заказчики) и ORDERS (их заказы) из базы данных BCDEMOS и используется компонент DBLookupListBox для того, чтобы отобразить на экране имя компании, соответствующее значению CustID, находящемуся в таблице ORDERS.
Чтобы создать форму для выведения на экран выбранных из таблицы ORDERS полей, следует открыть новый проект и сохранить главную форму как DBLOOK1.CPP, а проект как DBLOOK.MAK. Далее нужно разместить на форме компоненты TTable, DataSource, DBGrid и DBNavigator. Далее следует присвоить свойству Database Name компонента Table1 значение BСDEMOS, свойству TableName - значение ORDERS.DB, а свойству Active - значение true. Свойству DataSet компонента DataSource1 присвоим значение Table1, а свойству AutoEdit - значение false. Свойству DataSource компонентов DBGrid1 и DBNavigator1 присвоим значение DataSource1. Далее используем Fields Editor, чтобы внести в набор данных Table1 поля OrderNo, CustNo, SaleDate, ItemsTotal, AmountPaid. Расположим поля в Fields Editor так, чтобы OrderNo был бы первым, а CustNo - вторым. Можно скомпилировать и сохранить это приложение, затем запустить и протестировать его.
Теперь внесем в приложение компонент DBLookupListBox и установим его свойство DataSource равным DataSource1, а свойство DataField равным CustNo. Поместим на форму новые компоненты TTable и DataSource. Установим свойство DatabaseName для компонента Table2 равным BCDEMOS, свойство TableName равным CUSTOMER.DB, а свойство Active равным true. Свяжем DataSource2 с Table2. Свяжем компонент DBLookupListBox1 с DataSource2, установив значение свойства ListSource компонента DBLookupListBox1 равным DataSource2, свойства KeytField равным CustNo, а свойства ListField равным Company. Можно скомпилировать и сохранить приложение, затем запустить и протестировать его.
В компоненте DBLookupListBox будет выделено название компании, соответствующее значению CustNo в текущей строке DBGrid (рис. 9). Можно использовать DBLookupListBox для выбора заказчика по имени, при этом в таблице Orders будет устанавливаться соответствующее значение CustNo.
Рис. 9. Приложение с компонентом DBLookupListBox.
В следующих статьях будет рассмотрено использование компонента TQuery и возможности создания и использования SQL-запросов в приложениях С++ Builder.
| |
Пример использования компонента TQuery
Попробуем применить полученные сведения для создания приложения, использующего компоненты TTable, TQuery, TDataSource, TDBGrid. Воспользуемся для этой цели таблицами Customer.db и Orders.db, имеющимися в базе данных BCDEMOS, входящей в комплект поставки Borland C++ Builder. Данное приложение должно будет выводить списки клиентов из таблицы Customer, их заказов из таблицы Orders, а также позволять выбирать диапазон номеров клиентов.
Создадим новый проект и сохраним его главную форму как CUST1.CPP, а проект как CUST.MAK.
Изменим заголовок заголовок формы на "Контроль заказов". Разместим на форме компонент TDBGrid, два компонента TGroupBox, один компонент TTable, два компонента TQuery, три компонента TDataSource. На компонент GroupBox1 поместим три компонента TRadioButton и два компонента TButton. На компонент GroupBox2 поместим два компонента TEdit, два компонента TEdit и один компонент TButton.
Рис. 11. Расположение компонентов на форме приложения CUST
Установим следующие свойства для этих компонентов:
Table1 | DatabaseName | BCDEMOS |
TableName | CUSTOMER.DB | |
Active | false | |
DataSource1 | DataSet | Table1 |
DBGrid1 | DataSource | DataSource1 |
Query1 | Database Name | BCDEMOS |
SQL | select * from orders | |
Active | false | |
DataSource2 | DataSet | Query1 |
Query2 | DatabaseName | BCDEMOS |
DataSource3 | DataSet | Query2 |
Button1 | Caption | Открыть список &клиентов |
Button2 | Caption | Открыть список &заказов |
RadioButton1 | Caption | Клиенты |
Checked | true | |
RadioButton2 | Caption | Заказы |
GroupBox1 | Caption | |
GroupBox2 | Caption | |
Button3 | Caption | Установить &диапазон |
Edit1 | Text | |
Edit2 | Text | |
Label1 | Caption | Начало: |
Label2 | Caption | Конец: |
RadioButton3 | Caption | Заказы клиентов |
Создадим обработчик события OnClick для кнопки Button1:
void __fastcall TForm1::Button1Click(TObject *Sender) { if (Table1->Active) { Table1->Close(); Button1->Caption = "Ioe?uou nienie &eeeaioia"; } else { Table1->Open(); Button1->Caption= "Cae?uou nienie &eeeaioia"; } }
Теперь при нажатии на эту кнопку таблица Customer будет то открываться, то закрываться, при этом будет изменяться и надпись на кнопке.
Создадим обработчик события OnClick для кнопки Button2:
void __fastcall TForm1::Button2Click(TObject *Sender) { if (Query1->Active) { Query1->Active = false; Button2->Caption = "Ioe?uou список &caeacia"; } else { Query1->Active = true; Button2->Caption = "Заe?uou список &caeacia"; } }
При нажатии на кнопку Button2 будет то открываться, то закрываться запрос Query1, содержащий список заказов:
Создадим обработчики событий OnClick для радиокнопок RadioButton1 и RadioButton2:
void __fastcall TForm1::RadioButton1Click(TObject *Sender) { DBGrid1->DataSource = DataSource1; } //------------------------------------------------------------------------ void __fastcall TForm1::RadioButton2Click(TObject *Sender) { DBGrid1->DataSource =DataSource2; }
Теперь с помощью этих радиокнопок можно переключаться между списком клиентов и списком заказов.
Создадим обработчик события OnClick для кнопки Button3:
void __fastcall TForm1::Button3Click(TObject *Sender) { if (Table1->Active) { Table1->SetRangeStart(); Table1->Fields[0]->AsString = Edit1->Text; Table1->SetRangeEnd(); Table1->Fields[0]->AsString = Edit2->Text; Table1->ApplyRange(); } }
Теперь с помощью полей редактирования Edit1 и Edit2 и кнопки Button3 можно выбрать диапазон номеров клиентов для отображения сведений о них в DBGrid1.
Затем с помощью Visual Query Builder установим свойство SQL компонента Query2. Выберем в качестве имени базы данных BCDEMOS и внесем в запрос таблицы CUSTOMER и ORDERS. Затем установим связь между таблицами, проведя линию от поля CustNo в таблице CUSTOMER к полю CustNo в таблице ORDERS.
Внесем в запрос следующие поля:
Customer.CustNo Customer.Company Orders.OrderNo Orders.AmountPaid
Рис. 12. Использование Visual Query Builder для создания комбинированного запроса
Теперь отсортируем результаты запроса по номеру покупателя и выйдем из Visual Query Builder.
Используя инспектор объектов, выберем компонент Query2 и установим его свойство Active равным true.
Создадим обработчик события OnClick для RadioButton3:.
void __fastcall TForm1::RadioButton3Click(TObject *Sender) { DBGrid1->DataSource= DataSource3; }
Скомпилируем приложение. Щелкнем кнопками и "Открыть список заказов", чтобы открыть оба набора данных. Попробуем, используя радиокнопки, переключаться между ними.
Рис. 13. Так выглядит готовое приложение
Нажмем кнопку "Открыть список клиентов". Введем значения полей "Начало" и "Конец" (например, 1200 и 1700 соответственно) и затем нажмем кнопку "Установить диапазон". Убедимся, что значения номеров заказов действительно находятся в пределах этого диапазона.
Щелкнем на радиокнопке "Заказы клиентов" и убедимся, что результирующий набор данных действительно содержит сведения из обеих таблиц.
| |
SQL Explorer и словарь данных
SQL Explorer является удобным инструментом при работе с базами данных. Для его запуска следует выбрать пункт меню Database/Explore или запустить его в качестве отдельного приложения. В левой части окна Explorer на странице Databases представлены в виде раскрывающегося списка свойства всех описанных в файле конфигурации BDE псевдонимов. В правой части окна можно просмотреть содержимое таблиц, ввести и выполнить SQL-запрос к таблице, а также получить сведения о псевдонимах баз данных (драйвер БД, местоположение, используемый языковый драйвер и иные параметры, содержащиеся в файле конфигурации BDE), сведения о таблицах (тип таблицы, версия, дата последнего обновления и др.) и, при необходимости, внести в них изменения.
Рис. 15. SQL Explorer
Сам словарь данных доступен для просмотра на странице Dictionary. В нем в виде раскрывающегося списка содержатся сведения о базах данных и расширенных атрибутах полей таблиц (раздел Attribute Sets), в число которых входят, например, максимальное и минимальное значение для данного поля, значение по умолчанию, тип и класс контрольного элемента, метка при отображении на форме, маска редактирования и другие атрибуты, не содержащиеся непосредственно в таблицах, но характеризующие модель данных.
Рис.16. Просмотр и модификация словаря данных в SQL Explorer
Отметим, что пользователь может создавать свои словари данных (пункт меню Dictionary/New). По умолчанию словари данных создаются в виде таблиц формата Paradox, но не возбраняется хранить их в других форматах или на серверах баз данных (это имеет смысл при работе над крупными проектами).
|
Visual Query Builder
Visual Query Builder (VQB) является визуальным средством для построения запросов, базирующихся на SQL. С помощью этого средства можно строить комплексные запросы, обладая некоторыми знаниями SQL или не имея таких знаний вовсе. Запросы строятся шаг за шагом путем последовательного добавления выражений, таблиц, полей и отношений, пока не получится требуемый результат.
Visual Query Builder можно вызвать, выбирая компонент TQuery и нажимая правую кнопку мыши, после чего появляется контекстное меню, из которого следует выбрать опцию Query Builder.
Примечание. Visual Query Builder входит в комплект поставки не всех версий Borland C++ Builder либо может быть не установлен. В этом случае в контекстном меню может не быть соответствующей опции.
После выбора Query Builder на экране появится диалоговая панель Databases, позволяющая выбрать БД и осуществить соединение с ней (рис. 1).
Рис. 1. Выбор псевдонима базы данных
После соединения с базой данных на экран выводится окно Visual Query Builder и диалоговая панель для выбора таблиц, используемых в запросе (рис. 2).
Рис.2. После соединения с БД появляется окно Visual Query Builder и диалоговая панель Add Table.
Панель инструментов Visual Query Builder позволяет выбирать операции, которые можно выполнить при создании, тестировании и просмотре текста запроса. Таблица 8.1 описывает назначения кнопок на панели инструментов Visual Query Builder:
Таблица 1. Панель инструментов Visual Query Builder
New | Создает новый запрос. | ||
Open | Открывает файл запроса. | ||
Save As | Сохраняет запрос в файле. | ||
Options | Помещает на экране диалоговую панель Options, позволяющую установить различные опции запроса. | ||
Table | Помещает на экран диалоговую панель Add Table, позволяющую вносить таблицы в оператор SQL. | ||
Expression | Помещает на экран диалоговую панель Expression, позволяющую создавать вычисляемые поля, допустимые с точки зрения языка SQL. | ||
SQL | Выводит окно с текстом сгенерированного SQL-запроса. | ||
Run | Выполняет сгенерированный запрос и выводит на экран результаты. | ||
OK | Устанавливает свойство SQL компонента TQuery равным сгенерированному запросу и закрывает Visual Query Builder. | ||
Cancel | Отменяет присвоение свойства SQL компонента TQuery и закрывает Visual Query Builder. | ||
Help | Выводит на экран оперативную помощь для Visual Query Builder. |
Диалоговая панель Add Table (рис. 2) появляется при открытии Visual Query Builder или при выборе соответствующей кнопки диалоговой панели. Она позволяет вносить в запрос таблицы, выводя список всех таблиц в текущей БД. Если отметить опцию Include System Tables, для построения запроса будут доступны системные таблицы данной БД.
Рис. 3. В рабочем пространстве окна Visual Query Builder появится таблица, выбранная из списка
Для внесения одной или более таблиц в запрос следует выполнить следующее:
Если диалоговая панель Add Table не присутствует на экране, щелкнуть кнопкой Table на панели инструментов, чтобы вывести ее на экран. Выбрать имя таблицы из списка таблиц в диалоговой панели и щелкнуть на кнопке Add. Описание структуры выбранной таблицы появится в верхней части окна окна Visual Query Builder. Повторить п.2, пока все требуемые таблицы не будут внесены в запрос, и затем нажать кнопку Close.
Чтобы внести колонку одной из таблиц в запрос, нужно выбрать имя колонки и затем перетащить эту колонку и поместить ее на таблицу в нижней части окна, либо дважды щелкнуть на имени колонки. Для выбора всех полей таблицы следует перетащить в нижнюю часть окна значок * , находящийся над списком полей таблицы.
Рис. 4. Создание комбинированного запроса
Чтобы скомбинировать информацию из нескольких таблиц, нужно определить, как будут соединяться разные таблицы. С помощью Visual Query Builder можно определить колонки, имена которых служат для связи таблиц. С этой целью нужно выбрать имя колонки, по которой осуществляется межтабличная связь, в одной из связываемых таблиц, нажать левую клавишу мыши и переместить курсор (он изменит форму) на имя соответствующей колонки другой таблицы. В результате в рабочем пространстве запроса образуется линия, связывающая колонки этих двух таблиц (рис. 8.7).
Можно просмотреть или отредактировать критерий соединения таблиц, два раза щелкнув на линии, показывающей это соединение в верхней части окна Visual Query Builder. При этом появляется диалоговый блок Join (рис.5):
Рис. 5. Выбор критерия соединения таблиц
Чтобы определить критерий отбора для запроса, нужно использовать строку Criteria таблицы в нижней части окна Visual Query Builder.
Строка Criteria допускает любые выражения запроса, являющиеся допустимыми с точки зрения предложения WHERE оператора SQL (табл. 2).
Таблица 2. Допустимые выражения в предложении WHERE SQL-запроса
= | Равно |
> | Больше, чем |
< | Меньше, чем |
!= | Не равно |
like | Строка символов в сравнении с образцом. |
Between | Не меньше, чем начальное значение и не больше, чем конечное. |
In | Содержится в списке |
Условия OR вводятся как выражения в строку OR (ниже строки Criteria).
Можно отсортировать результаты в восходящем (ascending) или нисходящем (descending) порядке для выбранной колонки. Чтобы определить порядок сортировки для колонки, следует поместить указатель мыши на колонке около строки Sort , щелкнуть правой кнопкой мыши и выбрать Ascending или Descending из контекстного меню.
Можно сгруппировать результаты запроса, используя строку Option.
Если для какой-либо колонки нужно определить опции представления данных в запросе, следует поместить курсор на колонке около строки Option, щелкнуть правой кнопкой мыши, чтобы вывести на экран контекстное меню Option и выбрать нужную опцию.
Рис. 6. Выбор опции для колонки
Можно определить условия для результатов группировки, используя строку Group Condition, что эквивалентно внесению выражения с предложением HAVING в SQL-операторе SELECT, использующем предложение GROUP BY.
Visual Query Builder позволяет определить выражения как часть запроса. Выражения представляют собой операции вычислений на основе числовых значений, строковые операции и т.д.
Чтобы создать вычисляемое поле, следует щелкнуть кнопкой Expression на панели инструментов. Появится диалоговая панель Expression ( см. рис. 7).
Рис. 7. Вызов диалоговой панели Expression .
Диалоговая панель Expression позволяет использовать в запросах арифметические операции умножения, деления, сложения, вычитания, имена колонок и составные выражения, такие как avg, count, min, max и sum. Можно редактировать вручную или строить выражения, используя блок редактора Expression.
Рис. 8. Диалоговая панель Options
Диалоговая панель Options (рис. 8) используется для того, чтобы определить опции для оператора SQL. Можно, например, удалить повторяющиеся записи (Remove Duplicate Records), использовав предложение DISTINCT оператора SQL. Чтобы вызвать диалоговую панель Options, нужно щелкнуть кнопкой Options на панели инструментов.
Можно выполнить запрос, сгенерированный Visual Query Builder. Результаты запроса отобразятся на экране в диалоговой панели Result Window (окно результатов). Это окно позволяет убедиться, что колонки запроса, критерий выбора, критерии группировки и сортировки были определены корректно. Чтобы выполнить запрос, нужно щелкнуть кнопкой Run на панели инструментов. Появится окно Result Window, подобное представленному на рис. 8.
Рис. 9. Результаты запроса отобразятся на экране в Result Window
Можно проверить текст запроса, просматривая окно SQL Statement, для чего следует щелкнуть на кнопке SQL на панели инструментов. Это окно показывает сгенерированный оператор SQL. При добавлении или изменении колонок запроса, критерия отбора, критерия группировки или сортировки содержимое окна SQL Statement редактируется автоматически (рис. 10).
Рис. 10. Сгенерированный оператор SQL в окне SQL Statement.
Для завершения работы Visual Query Builder следует нажать кнопку с зеленой галочкой на инструментальной панели. После этого свойству SQL компонента TQuery, для которого был активизирован Visual Query Builder, будет присвоен сгенерированный текст SQL-запроса.
| |
можно создать приложения, работающие как
Используя Borland C++ Builder, можно создать приложения, работающие как с однопользовательскими базами данных (БД), так и с серверными СУБД, такими как Oracle, Sybase, Informix, Interbase, MS SQL Server, DB2, а также с ODBC-источниками. Возможности C++ Builder, связанные с созданием приложений, использующих базы данных, весьма обширны для того, чтобы описать их в одной статье. Поэтому сегодня мы рассмотрим лишь простейшие возможности работы с таблицами баз данных.
Набор данных в C++ Builder - это объект, состоящий из набора записей, каждая из которых, в свою очередь, состоит из полей, и указателя текущей записи. Набор данных может иметь полное соответствие с реально существующей таблицей или быть результатом запроса, он может быть частью таблицы или объединять между собой несколько таблиц.
Набор данных в C++ Builder является потомком абстрактного класса TDataSet (абстрактный класс - это класс, от которого можно порождать другие классы, но нельзя создать экземпляр объекта данного класса). Например, классы TQuery, TTable и TStoredProc, содержащиеся на странице палитры компонентов Data Access, - наследники TDBDataSet, который, в свою очередь, является наследником TDataSet. TDataSet содержит абстракции, необходимые для непосредственного управления таблицами или запросами, обеспечивая средства для того, чтобы открыть таблицу или выполнить запрос и перемещаться по строкам.
Borland C++ Builder обладает широкими возможностями доступа к базам данных. Так как базы данных предназначены не только для хранения, но и для выбора и обработки информации, одним из важнейших аспектов их использования является создание запросов к ним. Поэтому сегодня мы рассмотрим, как в C++ Builder решаются проблемы построения запросов.
Запрос в C++ Builder - это объект, представляющий собой набор данных. Обычно для создания запроса используется компонент TQuery - потомок абстрактного класса TDataSet.
| |