5.2.1.2 Таблицы Компонента таблицы представляет собой один из самых фундаментальных и гибких компонентных классов. TTable устанавливает прямую связь с таблицей базы данных посредством BDE, причем все записи или столбцы этой таблицы становятся доступными для приложения - как раздельно, так и внутри определенного интервала адресов. Рис. 5.7 показывает свойства компоненты таблицы в окне Инспектора объектов:
TableName позволяет выбрать фактическое имя таблицы из выпадающего списка с именами всех таблиц в адресуемой базе данных. Exclusive разрешает или запрещает другому приложению обращаться к таблице, пока вы ее используете сами. Значение false запрещает исключительный доступ по умолчанию. IndexFiles открывает диалог выбора индексного файла для таблицы. IndexName задает правило отображаемых сортировки данных, отличное от упорядочивания по первичному ключу (primary key order). Filter позволяет устанавливать критерий фильтрации, в соответствии с которым адресуется некоторое подмножество записей таблицы. ReadOnly управляет правами доступа в процессе выполнения программы. Значение false разрешает запись по умолчанию. MasterFields и MasterSource участвуют в образовании связи двух таблиц (ведущей и ведомой) по принципу master-detail. Следующая процедура иллюстрирует процесс создания простой формы для демонстрационной базы данных BCDEMOS, в которой пользователь может прокручивать записи таблицы заказчиков CUSTOMER с отображением всех заказов таблицы ORDERS, сделанных текущим заказчиком. IndexName задает правило отображаемых сортировки данных, отличное от упорядочивания по первичному ключу (primary key order). Filter позволяет устанавливать критерий фильтрации, в соответствии с которым адресуется некоторое подмножество записей таблицы. ReadOnly управляет правами доступа в процессе выполнения программы. Значение false разрешает запись по умолчанию. MasterFields и MasterSource участвуют в образовании связи двух таблиц (ведущей и ведомой) по принципу master-detail. Следующая процедура иллюстрирует процесс создания простой формы для демонстрационной базы данных BCDEMOS, в которой пользователь может прокручивать записи таблицы заказчиков CUSTOMER с отображением всех заказов таблицы ORDERS, сделанных текущим заказчиком:
3. Установите свойства объекта ведомой таблицы Table2 DatabaseName = BCDEMOS TableName = ORDERS.DB Name = OrdersTable 4. Установите свойства объекта источника DataSource1l DataSet = CustomersTable Name = CustomersSource 5. Установите свойства объекта источника DataSource2 DataSet = OrdersTable Name = OrdersSource 6. Поместите на форму пару компонент управления сеткой TDBGrid. 7. Выполните команду File | Include Unit Hdr, чтобы указать, что данная форма должна использовать созданный модуль данных. 8. Установите свойство объекта первой сетки DBGrid1 9. Активизируйте таблицу OrdersTable модуля данных и установите свойство
10. Дважды щелкните мышью в графе значений свойства MasterFields, и в открывшемся окне дизайнера связи полей - выберите номер заказчика CustNo (связующее поле таблиц) из выпадающего списка Available Indexes; - задайте CustNo в списках Detail Fields и Master Fields; - нажмите кнопку Add, чтобы добавить в список Joined Fields соединение CustNo -> CustNo; - нажмите кнопку OK, подтверждая сделанный выбор. 11. Установите свойство Active = true для таблиц CustomersTable и OrdersTable с тем, чтобы сразу же отобразить живые данные в сетках на форме. 12. Скомпилируйте и запустите приложение. Рис. 5.9 показывает работу связанных таблиц: при прокрутке записей таблицы заказчиков вы увидите только те записи в таблице заказов, которые относятся к текущему заказчику. Рис. 5.9. Связь таблиц по принципу master-detail. Методы Locate и Lookup используются для поиска указанных записей как в индексных таблицах, так и в таблицах с ключами: эти методы реализуют самый быстрый из возможных способов поиска в данной таблице. Если столбцы для поиска индексированы и индекс совместим с указанными опциями, используется способ индексного поиска. В противном случае методы создают для BDE соответствующий фильтр. Locate производит поиск специфической записи и позиционирует курсор на нее. В простейшем варианте вы передаете методу название столбца для поиска, искомое значение ключа записи и флаг опций. Листинг 5.2 содержит фрагмент кода, обеспечивающего поиск в столбце "Имя" таблицы MyTable первой записи со значением "Иван". Если поиск завершился успешно, Locate возвращает значение true, и найденная запись становится текущей. Если искомая запись не найдена, Locate возвращает значение false, и позиция курсора не меняется. { Листинг 5.2. Простейший пример использования метода Locate. Возможности метода проявляются при поиске вариантных значений записи в нескольких столбцах таблицы. Обобщенный синтаксис описания метода имеет следующий вид: bool __fastcall Locate(const AnsiString KeyFields, const Variant SKeyValues, TLocateOptions Options); В главе 3 отмечалось, что различные типы искомых значений объявляются в шаблонном классе Variant (с помощью которого C++Builder реализует одноименный встроенный тип Delphi). Названия столбцов для поиска разделяются в текстовой строке параметра KeyFields символом точка с запятой. Lookup выбирает значения столбца той записи, которая удовлетворяет заданным значениям поиска. Позиция курсора не меняется. В простейшем варианте вы передаете методу название столбца для поиска, искомое значение ключа записи и возвращаемые поля этой записи. Листинг 5.3 содержит фрагмент кода, обеспечивающего поиск в таблице MyTable первой записи, у которой в столбце "Фирма" имеется значение "Borland". Если поиск завершился успешно, Lookup возвращает в массиве типа Variant название фирмы, фамилию ее представителя и номер телефона. Если искомая запись не найдена, Lookup возвращает значение Null. { Листинг 5.3. Простейший пример использования метода Lookup. Возможности метода проявляются при поиске вариантных значений полей записи в нескольких столбцах таблицы. Обобщенный синтаксис описания метода имеет следующий вид: Variant _fastcall Lookup(const AnsiString KeyFields, const Variant sKeyValues, const AnsiString ResultFields); Названия столбцов для поиска разделяются в текстовой строке параметра KeyFields символом точка с запятой. С компонентой TTable также связаны следующие методы: • GotoCurrent синхронизирует перемещения курсора по нескольким табличным компонентам, ассоциированным с одной и той же фактической таблицей базы данных. • First, Next, Prior, Last и MoveBy используются для навигации по данным таблицы. • SetKey, FindKey, FindNearest, GotoKey и GotoNearest используются для поиска по специфическим значениям ключей. • Append, Insert, AppendRecord и InsertRecord добавляют новую запись к таблице. Delete вычеркивает текущую запись. Edit разрешает приложению модифицировать записи, a Post вызывает фактическое изменение содержимого базы данных. • EditRangeStart, EditRangeEnd, SetRangeStart, SetRangeEnd, ApplyRange и SetRange устанавливают границы интервала адресов записей, возвращаемых приложению при групповом доступе. 5.2.1.3 Запросы Компоненты таблиц являются полноправными, гибкими и легкими в использовании
компонентами доступа, достаточными для многих приложении СУБД. TTable
возвращает все строки и столбцы единственной таблицы, если доступ не ограничивается
установкой интервалов и фильтров. Компоненты запросов предоставляют разработчикам
альтернативные возможности. TQuery обеспечивает доступ к нескольким таблицам
одновременно и способна адресовать некоторое подмножество записей. Вид
возвращаемого набора данных (result set) зависит от формы запроса, который
может быть либо статическим, когда все параметры запроса задаются на стадии
проектирования, или динамическим, когда параметры определяются во время
выполнения программы. Рис. 5.10 показывает свойства компоненты запроса в окне Инспектора объектов:
Active разрешает или запрещает режим просмотра "живых данных", возвращаемых запросом на этапе проектирования. Значение false устанавливается по умолчанию. DatabaseName содержит псевдоним базы данных или полный путь к ее каталогу, необходимые для разрешения запроса. RequestLive разрешает или запрещает BDE сделать попытку возвратить "живой" результирующий набор. Значение false (устанавливается по умолчанию) указывает, что результаты запроса нельзя модифицировать. Значение true гарантирует возврат результирующего набора при условии, что синтаксис команды SELECT согласуется с требованиями запрашиваемых данных. SQL используется для ввода команды SQL посредством строчного
редактора списка, который открывается двойным щелчком мышью в графе значений
этого свойства. Локальные и удаленные серверы баз данных обеспечивают
выполнение четырех команд SQL: SELECT - для выбора существующих данных
из таблиц; INSERT - для добавления новых данных в таблицы; UPDATE - для
модификации данных таблиц; DELETE -для удаления данных из таблиц. Результаты
обработки запроса возвращаются приложению клиента. 1. Поместите компоненту TQuery на форму. 2. Установите псевдоним адресуемой базы данных сервера в свойстве DatabaseName. В примере используется псевдоним BCDEMOS локальной демонстрационный базы данных, содержащей, в частности, таблицу служащих некоторого предприятия. 3. Откройте строчный редактор списка, введите команду SQL SELECT * FROM EMPLOYEE WHERE Salary>40000 и нажмите кнопку ОК. 4. Поместите на форму компоненту TDataSource и установите ее свойство DataSet = Query1. 5. Поместите на форму компоненту управления сеткой TDBGrid и установите ее свойство DataSource = DataSource1. 6. Установите свойство Active = true для запроса Query1 с тем, чтобы сразу же отобразить живые данные в сетке (Рис. 5.11). Рис. 5.11. Форма приложения со статическим запросом к таблице служащих. Свойство SQL имеет объектный тип TStrings и заключает список текстовых строк наподобие массива. Листинг 5.4 показывает обработчик события ButtonlClick, реализующий ввод запроса пользователем при нажатии кнопки на форме. Введенная команда SQL записывается в строчный массив (того же типа TStrings) свойства Memol->Lines компоненты редактирования TMemo. Результаты запроса можно, как и в предыдущем примере, отобразить на сетке. void_fastcall TFormI::ButtonlClick(TObject *Sender) Листинг 5.4. Ввод и исполнение команды SQL. Params позволяет специфицировать имена, типы и начальные значения параметров запроса. C++Builder дает возможность конструировать команду SQL динамического запроса с параметрами. Чтобы указать нужный параметр динамического запроса, используйте символ двоеточия перед именем этого параметра. Например, параметр номера служащего в таблице employee идентифицируется следующей командой SQL: SELECT * FROM employee WHERE EmpNo = :EmpNo. Увидеть или поменять атрибуты выбранного параметра можно посредством диалогового редактора (Рис. 5.12), который открывается двойным щелчком мышью в графе значений этого свойства. Нажатие кнопки ОК подготавливает SQL сервер к запросу и вызывает попытку его выполнения на стадии проектирования приложения. Рис. 5.12. Редактор параметров запроса. Свойство Params содержит указатель на объект типа TParams. Поэтому изменить значение параметра во время выполнения программы можно по индексу в массиве Items объекта типа TParams: Query1->Params->Items[0]->AsInteger = 4; или по имени параметра, посредством метода ParamByName: Query1->ParamByName("FirstName") ->AsString = "John"; Листинг 5.5 дает законченный пример использования метода ParamByName во время исполнения программы. Параметр имени служащего FirstName идентифицируется следующей командой SQL: SELECT * FROM EMPLOYEE WHERE FirstName = :FirstName Заметим, что обработчик события первым делом обращается к методу подготовки запроса Prepare, посылая команду SQL серверу. Сервер выделяет ресурсы и оптимизирует динамический запрос только однажды, до первого исполнения. Все, что необходимо теперь, - это подставлять новые значения параметров и выполнять команду запроса с помощью метода Open. void __fastcall TForm1::Button1Click(TObject *Sender) Листинг 5.5. Изменение значения параметра динамического запроса. Рис. 5.13 показывает работу предыдущего примера: пользователь вводит значение параметра FirstName и в результате выполнения запроса получает список всех служащих с указанным именем. Рис. 5.13. Результат выполнения динамического запроса с параметром. DataSource указывает на источник другого набора данных, отличный от источника данного запроса, из которого вам надо выбрать значения текущего поля. Объект запроса будет сравнивать имя параметра в команде SQL с именами полей дочернего набора данных. Когда имена совпадают, параметр автоматически приобретает значение соответствующего поля. Следующая процедура иллюстрирует процесс создания формы, в которой запрос к таблице заказчиков CUSTOMER соединяется с таблицей заказов ORDERS по номеру заказчика CustNo: 1. Поместите компоненты TQuery и TTable на форму и установите псевдоним BCDEMOS в их свойствах DatabaseName. void _fastcall TPormI::DataSource2DataChange(TObject *Sender, TField
*Field) Листинг 5.6. Соединение запроса с таблицей по событию источника. Для динамического формирования текста командной строки SQL во время исполнения программы удобно использовать стандартную функцию Windows sprintf. Эта функция замещает параметры форматирования (%s, %d, %n и т.д.) передаваемыми значениями, например, в результате подстановки значений параметров форматирования: tbIName = "EMPLOYEE"; символьный массив sqls будет содержать следующую команду: "SELECT * FROM EMPLOYEE WHERE EmpNo =3" Листинг 5.7 иллюстрирует применение функции sprintf для формирования команды SELECT динамического запроса к таблице EMPLOYEE. Методы Clear и Add используются для занесения этой команды в свойство SQL. Поскольку подготовленный запрос использует ресурсы сервера и нет никакой гарантии, что новый запрос будет работать с данными одной и той же таблицы, C++Builder снимает готовность при любом изменении свойства SQL (т.е. устанавливает значение false свойства Prepared). При очередном исполнении запроса готовность автоматически восстанавливается. void __fastcall TForm1::Button1Click(TObject *Sender)
Листинг 5.7. Формирование команды SQL с помощью функции sprintf. Рис. 5.15 показывает работу предыдущего примера: в результате выполнения сформированного запроса пользователь получает список всех служащих, зарплата которых (выбранная из столбца Salary таблицы) оказывается меньше введенного значения. Рис. 5.15. Результат выполнения сформированного динамического запроса. Методы Open и ExecSQL предназначены для передачи серверу команды SQL для исполнения. В предыдущих примерах все запросы выдавали единственную команду SELECT. Результат запроса по команде select рассматривается как набор данных, точно так же, как при работе с таблицей. Существуют другие команды SQL, например, команда UPDATE, которая обновляет содержимое некоторой записи, но не возвращает какой бы то ни было результат. Для исполнения сервером таких запросов следует использовать метод ExecSQL вместо метода Open. Листинг 5.8 представляет собой некоторое обобщение всех рассмотренных ранее операций с динамическими запросами и их параметрами. Внимание: это приложение предназначено для управляемой модификации столбца Salary таблицы служащих EMPLOYEE из демонстрационной базы данных BCDEMOS. Изменения, внесенные командой UPDATE, необратимы, поэтому перед запуском собранного приложения позаботьтесь о том, чтобы сохранить копию оригинальной таблицы. По умолчанию С-н-Builder помещает все таблицы в каталоге инсталляции \.. .\CBuilder\Examples\Data.
|