|
.: Учебник для продвинутых по Delphi 7 :. ГЛАВА 12
Любое приложение баз данных должно уметь выполнять как минимум две операции. Во-первых, иметь информацию о местонахождении базы данных, подключаться к ней и считывать имеющуюся в таблицах БД информацию. Эта функция в значительной степени зависит от реализации конкретной технологии доступа к данным. Во-вторых, обеспечивать представление и редактирование полученных данных. Множество записей одной или нескольких таблиц, переданные в приложение в результате активизации компонента доступа к данным, будем называть набором данных. Понятно, что в объектно-ориентированной среде для представления какой-либо группы записей приложение должно использовать возможности некоторого класса. Этот класс должен инкапсулировать набор данных и обладать методами для управления записями и полями. Таким образом, сам набор данных и класс набора данных является той осью, вокруг которой вращается любая деятельность приложения баз данных. Пользователь просматривает на экране данные — это результат использования набора данных. Пользователь решил изменить какое-то число — он изменит содержимое ячейки набора данных. При закрытии приложение сохраняет все изменения — это набор данных передается в базу данных для сохранения. При этом, используя одни базовые функции для обслуживания набора данных, компоненты должны обеспечивать доступ к данным в рамках различных технологий. Поэтому не удивительно, что разработчики VCL уделили особое внимание созданию максимально эффективной иерархии классов, обеспечивающих использование наборов данных (рис. 12.1). Класс TDataset является базовым классом иерархии, он инкапсулирует абстрактный набор данных и реализует максимально общие методы работы с ним. В него можно передать записи из таблицы базы данных или строки из обычного текстового файла — набор данных будет функционировать одинаково хорошо. Рис. 12.1. Иерархия классов, обеспечивающих функционирование набора данных На основе базового класса реализованы специальные компоненты VCL для различных технологий доступа к данным, которые позволяют разработчику конструировать приложения баз данных, используя одни и те же приемы и настраивая одинаковые свойства. В этой главе рассматриваются следующие вопросы:
В основе иерархии классов, обеспечивающих функционирование наборов данных в приложениях баз данных Delphi, лежит класс TDataSet. Хотя он почти не содержит методов, реально обеспечивающих работоспособность основных механизмов набора данных, тем не менее его значение трудно переоценить. Этот класс задает структурную основу функционирования набора данных. Другими словами, это скелет набора данных, к методам которого необходимо лишь добавить требуемые вызовы соответствующих функций реальных технологий. При решении наиболее распространенных задач программирования в процессе создания приложений баз данных класс TDataSet не нужен. Тем не менее знание основных принципов работы набора данных всегда полезно. Кроме этого, класс TDataSet может использоваться разработчиками в качестве основы для создания собственных компонентов. Поэтому рассмотрим основные механизмы, реализованные в наборе данных. Набор данных открывается и закрывается свойством
которому соответственно необходимо присвоить значение True или False. Аналогичные действия выполняют методы
После открытия набора данных можно перемещаться по его записям. На одну запись вперед и назад перемещают курсор соответственно методы
На первую и последнюю запись можно попасть, используя соответственно методы
Признаком того, что достигнута последняя запись набора, является свойство
которое в этом случае имеет значение True. Аналогичную функцию для первой записи выполняет свойство
Перемещение вперед и назад на заданное число записей выполняет метод
Параметр Distance определяет число записей. Если параметр отрицательный — перемещение осуществляется к началу набора данных, иначе — к концу. Для ускоренного перемещения по набору данных можно отключить все связанные компоненты отображения данных. Это делается методом
Обратная операция выполняется методом
Общее число записей набора данных возвращает свойство
однако использовать его нужно аккуратно, т. к. каждое обращение к этому свойству приводит к обновлению набора данных, что может вызвать проблемы для больших таблиц или сложных запросов. Если вам нужно определить, не является ли набор данных пустым (часто используемая операция), можно использовать метод
который возвращает значение True, если набор данных пуст, или уже упоминавшиеся свойства
Номер текущей записи позволяет узнать свойство
Размер записи в байтах возвращает свойство
Каждая запись набора данных представляет собой совокупность значений полей таблицы. В зависимости от типа компонента и его настройки, число полей в наборе данных может изменяться. И совсем не обязательно набор данных должен содержать все поля таблицы базы данных. Совокупность полей набора данных инкапсулирует свойство
а все необходимые параметры полей содержатся в свойстве
Общее число полей набора данных возвращает свойство
а общее число полей типа BLOB содержится в свойстве
Доступ к значениям полей текущей записи предоставляет свойство
где в параметре FieldName задается имя поля. В процессе программирования разработчик очень часто обращается к полям набора данных. Если структура полей набора данных жестко задана и не изменяется, это можно сделать так:
Иначе, если порядок следования полей и их состав меняется, можно использовать метод
И делается это следующим образом:
Имя поля, передаваемое в параметре FieldName, не чувствительно к регистру символов. Метод
вернет в параметр List полный список имен полей набора данных. Более подробная информация о полях и способах работы с ними содержится в гл. 13. Класс TDataSet содержит ряд свойств и методов, которые обеспечивают редактирование набора данных. Но сначала бывает полезно поинтересоваться, можно ли редактировать набор данных вообще. Это можно сделать при помощи свойства
которое принимает значение True для редактируемых наборов. Перед началом редактирования набор данных нужно перевести в режим редактирования, использовав метод
Для сохранения сделанных изменений применяется метод
Разработчик может вызывать его самостоятельно, или же метод Post вызывается самим набором данных при переходе на другую запись. При необходимости все сделанные после последнего вызова метода Post изменения можно отменить методом
Новая пустая запись добавляется в конец набора данных методом
Новая пустая запись добавляется на место текущей методом
а текущая запись и все нижеследующие смещаются на одну позицию вниз. Внимание При использовании методов Append и insert набор данных переходит в режим редактирования самостоятельно. Дополнительно, у вас есть возможность добавить или вставить новую запись уже с заполненными полями. Для этого применяются методы
А делается это примерно так:
После вызова этих методов и их завершения набор данных автоматически возвращается в состояние просмотра. Для существующей записи аналогичным образом можно заполнить все поля, использовав метод
Текущая запись удаляется методом
При этом набор данных не выдает никаких предупреждений, а просто делает это. Очистить содержимое всех полей текущей записи может метод
Обратите внимание, что поля становятся пустыми (NULL), а не сбрасываются в нулевое значение. О том, редактировалась ли текущая запись, сообщает свойство
если оно имеет значение True. Набор данных можно обновить, не закрывая и не открывая его снова. Для этого применяется метод
Однако он сработает только для таблиц и тех запросов, которые нельзя редактировать. В каждый момент времени набор данных находится в определенном состоянии (о состояниях см. ниже в этой главе). Свойство
дает информацию о текущем состоянии набора. Методы-обработчики класса TDataSet предоставляют разработчику широчайшие возможности по отслеживанию событий, происходящих с набором данных. По паре методов-обработчиков (до и после события) предусмотрено для следующих событий в наборе данных:
Обратите внимание, что помимо методов-обработчиков режима вставки существует дополнительный метод
который вызывается непосредственно при вставке или добавлении записи. Дополнительно к этому могут использоваться методы-обработчики возникающих ошибок. Они предусмотрены для ошибок удаления, редактирования и сохранения изменений. Метод-обработчик
очень важен для задания значений вычисляемых полей. Он вызывается для каждой записи, которая отображается в визуальных компонентах, связанных с набором данных каждый раз, когда необходимо перерисовать значения полей в визуальных компонентах. Если в методе-обработчике OnCalcFields производятся слишком сложные вычисления, частота его вызовов может быть уменьшена за счет свойства
По умолчанию оно равно значению True и расчет вычисляемых полей производится при каждой перерисовке. При значении False метод-обработчик OnCalcFields вызывается только при открытии, переходе в состояние редактирования и обновлении набора данных. Все перечисленные выше обработчики имеют одинаковый тип
И метод-обработчик
вызывается для каждой записи набора данных при свойстве Filtered = True. (Подробнее об этих свойствах и методе-обработчике см. гл. 14.) Помимо перечисленных, класс TDataSet содержит еще много свойств и методов, которые обеспечивают работоспособность многих полезных в практическом программировании приложений баз данных функций. Подробно они рассмотрены в гл. 14.
Внимательный читатель заметил, что на рис. 12.1 набор компонентов для каждой из представленных технологий доступа к данным примерно одинаков. Везде есть компонент, инкапсулирующий табличные функции, компонент запроса SQL и компонент хранимой процедуры. И хотя все они имеют разных ближайших предков, тем не менее, функциональность подобных компонентов в различных технологиях почти одинакова. Поэтому имеет смысл рассмотреть общие для компонентов свойства и методы, представив, что существуют некие виртуальные общие предки для таблицы, запроса и хранимой процедуры. Примечание Некоторые из описываемых ниже свойств и методов присутствуют не в каждой реализации компонентов.
Компонент таблицы обеспечивает доступ к таблице базы данных целиком, создавая набор данных, структура полей которого полностью повторяет таблицу БД. За счет этого компонент прост в настройке и обладает многими дополнительными функциями, которые обеспечивают применение табличных индексов. Но в практике программирования работа с таблицами целиком используется не так часто. А при работе с серверами баз данных промежуточное ПО, используемых технологий доступа к данным, все равно транслирует запрос на получение табличного набора данных в простейший запрос SQL, например:
В такой ситуации применение табличных компонентов становится менее эффективным, чем использование запросов. После соединения с источником данных (процесс подключения для каждой технологии подробно рассматривается в части IV) необходимо задать имя таблицы в свойстве
Иногда в свойстве TаblеТуре дополнительно задается тип таблицы. Если соединение с источником данных настроено правильно, имя таблицы можно выбрать из выпадающего списка свойства TableName. Преимуществом табличного компонента является использование индексов, которые ускоряют работу с таблицей. Все индексы, созданные в базе данных для таблицы, автоматически загружаются в компонент. Их параметры доступны через свойство
Подробно класс TIndexDefs рассматривается ниже в этой главе. При работе с компонентом разработчик имеет возможность управлять индексами. Существующий индекс можно выбрать в Инспекторе объектов в списке свойств
или использовать свойство
в котором можно задать произвольное сочетание имен индексированных полей таблицы. Имена полей разделяются символом точкой с запятой. Таким образом, при помощи свойства IndexFieldNames можно создавать составные индексы. Свойства IndexName и IndexFieldNames нельзя использовать одновременно. Число полей, используемых в текущем индексе табличного компонента, возвращает свойство
А свойство
представляет собой индексированный список полей, входящих в текущий индекс:
Для выполнения операций с таблицами и индексами целиком в табличных компонентах реализовано несколько методов. Метод
создает новую таблицу в базе данных, используя заданное имя и описание полей, и индексов из свойств TFieldDefs и TindexDefs. Если таблица с таким именем уже имеется в базе данных, то она будет уничтожена и создана заново с новой структурой и данными. Метод
удаляет из набора данных и таблицы базы данных все записи. Метод
уничтожает таблицу базы данных, связанную с компонентом. Набор данных должен быть закрыт. Метод
добавляет к таблице БД новый индекс. Параметр Name задает имя индекса. В параметре Fields через точку с запятой определяются имена полей, входящих в индекс. Параметр DescFields задает описание индекса из констант, объявленных в типе TIndexOption. Метод
уничтожает индекс. Кроме этого, табличные компоненты содержат свойства и методы, описываемые в гл. 14.
Компонент запроса предназначен для создания запроса SQL, подготовки его параметров, передачи запроса на сервер БД и представления результата запроса в наборе данных. При этом набор данных может быть редактируемым или нет. Любой компонент запроса, каждая строка набора данных которого однозначно связывается с одной строкой таблицы БД, может редактироваться. Например, запрос
редактировать можно. Если же приведенное правило не выполняется, то набор данных можно использовать только для просмотра, и, конечно, возможности компонентов здесь ни при чем. Куда, к примеру, записывать результаты редактирования записей следующего запроса:
Ведь в таком запросе каждая запись есть результат суммирования неизвестного заранее числа других записей. Тем не менее компоненты запросов предоставляют разработчику мощный и гибкий механизм работы с данными. С помощью компонентов запросов можно решать гораздо более сложные задачи, чем с табличными компонентами. В целом компонент запроса работает быстрее, т. к. структура возвращаемых запросом полей может изменяться, то экземпляры класса TFieldDef, хранящие информацию о свойствах полей, создаются по необходимости при запуске приложения. Табличный компонент создает все классы для описания полей в любом случае, поэтому в приложениях клиент-сервер табличный компонент может открываться медленнее, чем запрос. Рассмотрим общие свойства и методы компонентов запросов. Текст запроса определяется свойством
В свойстве
содержится окончательно подготовленный текст запроса перед пересылкой его на сервер. Выполнение запроса возможно тремя способами. Если запрос возвращает результат в набор данных, то применяется метод
или свойство
которому присваивается значение True. После выполнения запроса открывается набор данных компонента. Закрывается такой запрос методом
или тем же свойством Active. Если запрос не возвращает результат в набор данных (например, использует операторы INSERT, DELETE, UPDATE), то используется метод
и после выполнения запроса набор данных компонента не открывается. Попытка использовать для такого запроса метод open или свойство Active приведет к ошибке создания указателя на курсор данных. После выполнения запроса в свойстве
возвращается число обработанных при выполнении запроса записей. Для того чтобы разрешить редактирование набора данных запроса, необходимо свойству
присвоить значение True. Это свойство устанавливается, но не работает для запроса, результат которого не модифицируется из-за самого запроса. Для подготовки запроса к выполнению предназначен метод
который обеспечивает выделение необходимых ресурсов на сервере и проведение оптимизации. Метод
освобождает занятые при подготовке запроса ресурсы. Результат выполнения этих двух операций отражается в свойстве
Значение True данного свойства говорит о том, что запрос подготовлен для выполнения. Вызов методов Prepare и UPРrераrе не является обязательным, т. к. компонент делает это автоматически. Однако если запрос будет выполняться несколько раз подряд, то подготовку необходимо провести перед первым выполнением запроса вручную. Тогда при последующих выполнениях сервер не будет тратить время на проведение бесполезной операции — ведь ресурсы под запрос уже были выделены. Часто запросы имеют настраиваемые параметры, значения которых определяются непосредственно перед выполнением запроса. Свойство property Params: TParams; представляет собой список объектов TParams, каждый из которых содержит настройки одного параметра. Свойство Params обновляется автоматически при изменении текста запроса. Подробнее о классе TParams рассказывается ниже в этой главе. Примечание В компоненте TADOQuery свойство, аналогичное описанному свойству Params, называется Parameters. Свойство
возвращает число параметров запроса. Свойство
определяет, необходимо ли обновлять свойство Params при изменении текста запроса во время выполнения. При значении True обновление осуществляется. Кроме этого, компоненты запросов содержат некоторые свойства и методы, описываемые в гл. 14.
Компонент хранимой процедуры предназначен для определения процедуры, установки ее параметров, выполнения процедуры и возвращения результатов в компонент. В зависимости от выбранной технологии доступа к данным, каждый компонент хранимой процедуры имеет собственный способ соединения с сервером. После подключения к источнику данных имя хранимой процедуры можно выбрать из списка свойства
После этого свойство
предназначенное для хранения параметров процедуры, автоматически заполняется. Для хранимых процедур важно деление параметров на входные и выходные. Первые содержат исходные данные, а вторые передают результаты выполнения процедуры. Детально класс TParams описывается ниже. Общее число параметров возвращает свойство
Для подготовки хранимой процедуры используется метод
или свойство
которое должно получить значение True. Метод
или свойство Prepared := False выполняют обратное действие. Кроме того, проверка значения свойства Prepared позволяет установить, осуществлялась ли подготовка процедуры к выполнению или нет. Внимание После выполнения хранимой процедуры исходный порядок следования параметров в списке Params может измениться. Поэтому для доступа к конкретному параметру рекомендуется использовать метод
Если хранимая процедура возвращает набор данных, компонент можно открывать методом
или свойством
В противном случае для выполнения процедуры используется метод
и после этого выходные параметры получат вычисленные значения.
Важнейшей проблемой для любой БД является достижение максимальной производительности и ее сохранение при дальнейшем увеличении объемов хранимых данных. Использование индексов позволяет решить эту задачу. Индекс представляет собой часть базы данных, в которой содержится информация об организации данных в таблицах БД. В отличие от ключей, которые просто идентифицируют отдельные записи, индексы занимают дополнительные объемы памяти (довольно значительные) и могут храниться как совместно с таблицами, так и в виде отдельных файлов. Индексы создаются вместе со своей таблицей и обновляются при модификации данных. При этом работа по обновлению индекса для большой таблицы может отнимать много ресурсов, поэтому имеет смысл ограничить число индексов для таких таблиц, где происходит частое обновление данных. Индекс содержит в себе уникальные идентификаторы записей и дополнительную информацию об организации данных. Поэтому если при выполнении запроса сервер или локальная СУБД обращается для отбора записи к индексу, то это занимает значительно меньше времени, т. к. понятно, что идентификатор гораздо меньше самой записи. Кроме этого, индекс "знает", как организованы данные и может ускорять обработку за счет группирования записей по сходным значениям параметров. Создание для БД эффективного набора индексов является нетривиальной задачей. Во-первых, нужно верно определить оптимальное число индексов для каждой таблицы. Во-вторых, каждый индекс должен содержать только необходимые поля, при этом большую роль играет их упорядочивание. В большинстве СУБД при создании индексов требуется только задать поля и название индекса, вся остальная работа выполняется автоматически. Естественно, что в компонентах доступа к данным VCL Delphi используются все возможности такого мощного инструмента, как индексы. Причем свойства и методы для работы с индексами присутствуют только в табличных компонентах, т. к. в компонентах запросов работа с индексами осуществляется средствами SQL. Набор данных может работать и без применения индексов, но для этого соответствующая таблица БД не должна иметь первичного ключа — случай довольно редкий. Поэтому по умолчанию в наборе данных используется первичный индекс. При открытии набора данных все записи отсортированы в соответствии с первичным ключом.
Для того чтобы подключить к набору данных вторичный индекс, необходимо присвоить свойству indexName название индекса. Если свойство не имеет значения, то в наборе данных используется первичный индекс. Альтернативный способ задания индекса заключается в использовании свойства indexFieldNames, в котором задается перечень имен полей необходимого индекса, разделенных точкой с запятой. При этом в Инспекторе объектов для данного свойства список полей существующих индексов создается автоматически, разработчику остается сделать выбор. При помощи свойства indexFieldNames можно создавать и составные индексы. Для этого необходимо, чтобы все входящие в список поля были индексированы. Список имен всех индексов можно получить при помощи метода
Примечание Изменение текущего индекса можно осуществлять без отключения набора данных, поэтому в приложениях очень удобно делать сортировку данных по индексам. Такой метод смены индексов называется индексацией "на лету". После установки индекса количество полей в индексе передается в свойство
Информация об индексах набора данных содержится в свойстве класса
В нем для каждого индекса создается структура TindexDef. Доступ к информации об индексах осуществляется через свойство
являющееся списком объектов TindexDef. Объекты типа TindexDef можно добавлять в список при помощи метода
Поиск объекта описания индекса осуществляет метод
который возвращает найденный объект по заданному в параметре Name имени индекса. Пара методов
находит объект описания индекса по списку полей, входящих в индекс. Если индекс не найден, ищется первый индекс, начинающийся с указанных полей. Первый из этих двух методов в случае неудачного поиска генерирует исключительную ситуацию EDatabaseError, а второй возвращает nil. Список IndexDefs обновляется автоматически при открытии набора данных. Но метод
обновляет список описаний индексов без открытия набора данных.
Параметры каждого индекса набора данных представлены в классе TindexDef, а их совокупность для набора данных содержится в свойстве IndexDefs класса TDataSet. Свойство
определяет название индекса. Список всех полей индекса содержится в свойстве
Поля разделяются точкой с запятой. Свойство
содержит список полей, регистр символов в которых при сортировке не учитывается. Поля разделяются точкой с запятой. Все поля из этого списка должны входить в свойство Fields. В наборе данных по умолчанию используется сортировка записей с учетом регистра символов. Но некоторые серверы БД допускают комбинированную сортировку по полям с учетом регистра и без. Свойство
содержит список полей через точку с запятой, которые сортируются в обратном порядке. Все поля из этого списка должны входить в свойство Fields. По умолчанию все поля сортируются в прямом порядке. Некоторые серверы БД поддерживают одновременную сортировку полей в прямом и обратном порядке. Свойство
позволяет ограничить область применения индекса. Если значение этого свойства равно нулю, индекс упорядочивает все записи набора данных. В противном случае действие индекса распространяется на группы записей, имеющих одинаковые значения для того числа полей, которое задано этим свойством. Параметры индекса определяются свойством
Для индекса возможны сочетания следующих параметров:
Метод
заполняет свойства объекта значениями аналогичных свойств объекта ASource.
Использование описаний индексов Описания индексов наряду с описаниями полей (см. г/г. 13) также используются при создании новых таблиц БД. Для каждого планируемого индекса перед вызовом метода CreateTable необходимо создать или скопировать из существующего набора данных соответствующее описание. Тогда при создании таблицы индексы будут добавлены автоматически:
При создании описаний индексов использован метод AddlndexDef, который при каждом вызове добавляет к списку Items объекта TIndexDefs новый объект TindexDef. Таким образом сначала создается первичный индекс (в таблицах Paradox он не имеет имени), затем вторичный индекс SecondI"ndex. Для каждого описания обязательно определяются составляющие индекс поля и параметры индекса (свойства Fields и options).
Параметры запросов и хранимых процедур Свойство Params представляет собой набор изменяемых параметров запроса или хранимой процедуры, а также набор объектов TParam, инкапсулирующих отдельные параметры. Рассмотрим следующий запрос SQL:
В нем осуществляется отбор номеров заказов, сделанных в августе 2001 года. Теперь вполне естественно было бы предположить, что пользователю может понадобиться получить подобный отчет за другой месяц или за первые десять дней августа. В этом случае можно поступить так:
При создании формы в методе FormCreate задается текст запроса. Для этого используется свойство SQL. При щелчке на кнопке RunBtn, в соответствии с заданными в однострочных редакторах DatelEdit и Date2Edit датах, изменяется текст запроса. Метод FormCreate приведен только для того, чтобы обозначить первоначальный текст запроса, этот текст вполне можно задать в свойстве SQL. Для решения подобных задач как раз и используются параметры. В этом случае текст запроса будет выглядеть следующим образом:
Двоеточие перед именами PD1 и PD2 означает, что это параметры. Имя параметра выбирается произвольно. В списке свойства Params первым идет тот параметр, который расположен первым по тексту запросу. После ввода в свойстве SQL текста запроса для каждого параметра автоматически создается объект TParam. Эти объекты доступны в специализированном редакторе, который вызывается при щелчке на кнопке свойства Params в Инспекторе объектов (рис. 12.2). Для каждого параметра требуется установить тип данных, который должен согласовываться с типом данных соответствующего поля. Рис. 12.2. Специализированный редактор параметров запроса Теперь для задания текущих ограничений по дате поступления можно использовать свойство Params:
При щелчке на кнопке RunBtn при помощи параметров в запрос передаются текущие значения ограничений дат. Значения параметров запроса можно задать и из другого набора данных. Для этого применяется свойство DataSource компонента набора данных. Указанный в свойстве компонент TDataSource должен быть связан с набором данных, значения полей которого требуется передать в параметры. Названия параметров должны соответствовать названиям полей этого набора данных, тогда свойство DataSource начнет работать. При перемещении по записям набора данных текущие значения одноименных параметров полей автоматически передаются в запрос. Для иллюстрации работы этого свойства рассмотрим простой пример, главная форма которого представлена на рис. 12.3. Этот проект не имеет ни одной строки написанного вручную программного кода. Рис. 12.3. Главная форма проекта DemoQueryParams Верхний компонент TDBGrid отображает данные из таблицы Orders базы данных DBDEMOS и связан через компонент OrdersSource типа TDataSource с компонентом запроса ordersQuery. Текст запроса выглядит так:
Нижний компонент TDBGrid отображает данные о покупателе и через компонент CustSource типа TDataSource связан с запросом CustSource, свойство SQL которого имеет следующий вид:
Обратите внимание, что название параметра соответствует названию поля номера покупателя из таблицы Orders. Свойство DataSource компонента custQuery указывает на компонент OrdersSource. Как только оба набора данных открываются, текущее значение из поля CustNo набора данных orders автоматически передается в параметр запроса компонента CustQuery. Благодаря этому, для двух наборов данных реализована связь "один-к-одному" по полю номера поставщика. И в завершение разговора о параметрах запросов рассмотрим свойства и методы класса TParams, составляющего свойство Params, и класса TParam, инкапсулирующего отдельный параметр.
Класс TParams представляет собой список параметров. Доступ к элементам списка возможен через индексированное свойство
а к значениям параметров — через свойство
Добавить новый параметр можно методом
Но для него необходимо создать объект параметра. Это можно сделать методом
где FidType — тип данных параметра, ParamName — имя параметра и ParamType — тип параметра (см. ниже). И оба метода можно использовать в связке:
Вместо того, чтобы заполнять параметры по одному, можно использовать метод
который при DoCreate = True анализирует текст запроса из свойства SQL и создает новый список параметров. Или же, для присвоения значений сразу всем параметрам используется метод
Для удаления параметра из списка применяется метод
При работе с параметрами для их идентификации полезно использовать обращение по имени, т. к. при работе с хранимыми процедурами после их выполнения порядок следования может измениться. Также и при использовании динамических запросов (их текст SQL может изменяться во время выполнения). Для обращения к параметру по имени используется метод
В сложных запросах SQL или после многочисленных исправлений разработчик может допустить ошибку и создать два разных параметра с одним именем. В этом случае при выполнении запроса одноименные параметры считаются одним и им присваиваются значение первого по порядку запроса. Для контроля повторных имен в списке параметра используется метод
который возвращает значение True, если для параметра value найден дубликат.
Класс TParam инкапсулирует свойства отдельного параметра. Имя параметра определяется свойством
Тип данных параметра задает свойство
Тип данных параметра и связанного поля должны совпадать. Тип параметра определяется множеством
которое имеет следующие значения:
Свойство
определяет тип параметра. При работе с параметрами довольно часто бывает необходимо определить, имеет ли параметр ненулевое значение. Для этого используется свойство
Свойство возвращает значение True, если параметр не имеет значения или имеет значение Null. Свойство
возвращает значение True только тогда, когда параметру не присваивалось значение вообще. Метод
присваивает параметру значение Null. Само значение параметра задается свойством
Но использование вариантов не очень эффективно, когда требуется обеспечить максимальную скорость. В таких случаях можно обратиться к целому набору свойств AS ..., которые не только возвращают значение, но и приводят его к некоторому типу. Например, свойство
возвращает целочисленное значение поля. Примечание Необходимо осторожно использовать свойства с приведением типа, т. к. попытка преобразования неверного значения вызовет исключительную ситуацию. Для чтения из буфера и записи в буфер значения параметра соответственно используются методы
а необходимый размер при записи в буфер позволит определить метод
Можно скопировать тип данных, имя и значение параметра прямо из поля данных. Для этого применяется метод
а для присвоения типа данных и значения используется метод
Общее число знаков для числовых значений определяет свойство
А свойство
задает число знаков после запятой. Для строковых параметров размер задает свойство
В процессе своего функционирования (от открытия методом Open и до закрытия методом close) набор данных может выполнять самые разнообразные операции. Можно просто перемещаться по записям, можно редактировать данные и удалять записи, можно проводить поиск по различным параметрам и т. д. При этом желательно, чтобы все операции выполнялись как можно быстрее и эффективнее. Набор данных в любой момент времени находится в некотором состоянии, т. е. подготовлен к выполнению действий строго определенного рода. И для каждой группы операций набор данных выполняет ряд подготовительных действий. Все состояния набора данных делятся на две группы.
Базовый класс TDataSet, инкапсулирующий свойства набора данных, позволяет изменять состояние, а также проверять текущее состояние набора данных. Текущее состояние набора данных передается в свойство state, имеющее тип TDataSetState:
Для управления состояниями набора данных используются методы open, Close, Edit, Insert. Таблица 12.1. Автоматические состояния набора данных
Таблица 12.2. Управляемые состояния набора данных
Рассмотрим, как изменяется состояние набора данных при выполнении стандартных операций. Закрытый набор данных всегда имеет неактивное состояние dsinactive. При открытии набор данных переходит в состояние просмотра данных dsBrowse. В этом состоянии по записям набора данных можно перемещаться и просматривать их содержимое, но редактировать данные нельзя. Это основное состояние открытого набора данных, из него можно перейти в другие состояния, но любое изменение состояния происходит через просмотр данных (рис. 12.4). Рис. 12.4. Схема изменения состояний набора данных При необходимости редактирования данных набор должен быть переведен в состояние редактирования dsEdit, для этого используется метод Edit. После выполнения метода можно изменять значения полей для текущей записи. При перемещении на следующую запись набор данных автоматически переходит в состояние просмотра. Для того чтобы вставить в набор данных новую запись, необходимо использовать состояние вставки dsinsert. Метод insert переводит набор данных в это состояние и добавляет на месте текущего курсора новую пустую запись. При переходе на другую запись, после проверки на уникальность первичного ключа (если он есть) набор данных возвращается в состояние просмотра. Состояние установки ключа dsSetKey используется только в табличных компонентах при необходимости поиска методами FindKey и FindNext, а также при использовании диапазонов (метод setRange). Это состояние сохраняется до момента вызова одного из методов поиска по ключу или метода отмены диапазона. После этого набор данных возвращается в состояние просмотра. Состояние просмотра по блокам dsBlockRead используется набором данных при реализации быстрого перемещения по большим массивам записей без показа промежуточных записей в компонентах отображения данных и без вызова обработчика события перемещения по записям. Для реализации быстрого перемещения по набору данных можно использовать методы DisableControls И EnableControls.
Набор данных является образом таблицы базы данных в приложении. Он содержит группу записей и обеспечивает их использование. Класс TDataSet, инкапсулирующий функциональность набора данных, является базовым классом для всех технологий доступа к данным. На его основе созданы все основные компоненты, применяемые при разработке приложений баз данных. Условно их можно разделить на три группы:
В этой главе рассмотрены важнейшие свойства, методы и структуры, реализованные в компонентах, инкапсулирующих набор данных.
|
®Сайт разработал: Nek по вопросам пишите сюда NekSuper@yandex.ru |