У ряда компонентов доступа к данным, реализующим запросы (например, iBQuery и IBDataSet), свойство GeneratorField типа TIBGeneratorField позволяет присваивать значения первичным ключам набора данных с помощью генератора, назначаемого с использованием редактора названного свойства.
С помощью этого свойства можно обеспечить автоматическое задание значения одного из автоинкрементных полей, указав при этом, какое поле должно получать значение и как вычисляться (шаг изменения и событие: вставка записи, сохранение записи, по команде сервера). Для задания рассматриваемого свойства используется редактор (рис. 15.3), вызываемый двойным щелчком мыши в строке свойства в окне Инспектора объектов.
В окне редактора следует выбрать название генератора, имя автоинкрементного поля в таблице, для которого будут генерироваться значения, и шаг увеличения счетчика (обычно 1). Кроме того, нужно выбрать вариант события, при наступлении которого будет происходить генерация значения поля: On New Record (при вставке новой записи), On Post (при сохранении записи) и On Server (no команде сервера с помощью триггера).
436
Часть III. Удаленные базы данных
Доступ к таблицам
Для доступа к таблицам по технологии InterBase Express служит компонент iBTable. Рассмотрим кратко отличительные свойства этого компонента.
Размер буфера по числу записей определяет свойство BufferChunks типа Integer.
Тип отношений, доступных в дополнение к пользовательским таблицам при выборе в раскрывающемся списке с помощью свойства TableName, определяет свойство TableTypes типа TlBTableTypes. Оно может принимать следующие значения:
□ ttsystem — доступны системные таблицы и представления;
□ ttview — доступны пользовательские представления.
|
Существует ли в БД таблица, указанная с помощью свойства TableName, определяет свойство Exists типа Boolean. Это свойство рекомендуется проверять перед открытием таблицы при выполнении приложения.
При использовании компонента IBTable указывается только имя таблицы с помощью свойства TableName. При этом автоматически формируется запрос на выборку всей таблицы со всеми полями. Если в таблице имеется очень много записей, то после выполнения такого запроса на сервер может лечь чрезмерно большая нагрузка. К примеру, при выполнении операций поиска нужной записи. Поэтому в крупных программных приложениях БД использование компонента IBTable не рекомендуется.
Выполнение запросов
Для выполнения SQL-запросов по технологии InterBase Express служит компонент iBQuery. Этот компонент является аналогом компонента Query в технологии BDE. Рассмотрим кратко отличительные свойства компонента iBQuery.
Глава 15. Технология InterBase Express
437
Установить значение свойства sql типа TStrings, определяющего текст исполняемого SQL-запроса, можно с помощью редактора CommandText Editor, работа с которым описана в главе 9.
Параметры исполняемого SQL-запроса хранятся в свойстве Params типа TParams, а общее число параметров запроса возвращает свойство ParamCount типа word.
Специалисты рекомендуют использовать компонент Query в основном при переносе имеющихся приложений под BDE на платформу технологии InterBase Express. При разработке новых приложений взамен него предлагается использовать компонент iBDataSet.
Получение и редактирование данных
В рассматриваемой технологии для выполнения SQL-запросов по выборке, вставке, удалению и обновлению записей в таблицах и представления полученных наборов данных используется компонент IBDataSet. Этот компонент реализует практически все возможности описанных выше компонентов доступа к данным по рассматриваемой технологии, именно его и целесообразно использовать при разработке приложений БД.
|
На этапе разработки и при выполнении приложения для компонента IBDataSet доступны следующие свойства типа TStrings, задающие различные типы запросов:
□ insertSQL — на добавление записей в набор данных;
□ DeleteSQL — на удаление записей из набора данных;
□ ModifySQL — на изменение записей в наборе данных;
□ SelectSQL — запрос на выборку всех записей набора данных;
□ RefreshSQL — на обновление текущей записи набора данных.
Тип запроса к набору данных определяется с помощью свойства statementType типа TiBSQLTypes, который описан так:
type TiBSQLTypes = set of (SQLUnknown, SQLSelect, SQLInsert, SQLUpdate, SQLDelete, SQLDDL, SQLGetSegment, SQLPutSegment, SQLExecProcedure, SQLStartTransaction, SQLCommit, SQLRollback, SQLSelectForUpdate, SQLSetGenerator);
Здесь:
□ SQLCommit — фиксация текущей (активной) транзакции;
□ sqlddl — выполнение команды DDL;
□ SQLDelete — удаление записей в таблице или курсоре;
□ SQLExecProcedure — вызов хранимой процедуры;
□ SQLGetSegment — чтение сегмента BLOB;
□ SQLInsert — добавление записей в таблицу;
Часть III. Удаленные базы данных
П SQLPutsegment — запись сегмента BLOB;
□ SQLRoiiback — восстановление состояния БД, предшествовавшего началу текущей транзакции;
□ SQLSetForupdate — хранимая процедура, устанавливается для обновления;
□ SQLSetGenerator — установка нового значения для существующего генератора;
□ SQLSeiect — возвращение данных из одной или нескольких таблиц (SQL-запрос);
|
□ SQLStartTransaction — начало новой транзакции;
□ SQLUnknown — неизвестный тип SQL;
□ SQLUpdate — изменение записи в таблице, представлении или курсоре.
В целом компонент iBDataSet предназначен для выполнения модифицирующих запросов с целью изменения данных, полученных с помощью запроса на выборку, задаваемого в свойстве SelectSQL.
Рассмотрим технику выполнения модифицирующих запросов с использованием свойств ModifySQL, insertSQL, DeleteSQL и RefreshSQL компонента IBDataSet. Предположим, что с помощью запроса на выборку, заданного в свойстве SelectSQL, мы получили набор данных, содержащий записи с нужными полями заданной таблицы. Пусть нам требуется отредактировать содержимое одного из или нескольких полей некоторой записи. При этом после внесения изменений, например, в компоненте DBGrid, эти изменения будут внесены в локальный буфер, а в базе данных на сервере ничего не изменится. Для внесения соответствующих изменений в базе данных на сервере нужно выполнить оператор UPDATE языка SQL. Причем этот запрос должен быть указан в качестве значения свойства ModifySQL рассматриваемого компонента.
К примеру, если редактируемый набор данных для таблицы с именем 'country' содержит поля с именами 'country' и 'currency1, to соответствующий запрос на изменение записи в свойстве ModifySQL может содержать следующий текст:
UPDATE COUNTRY
SET
COUNTRY =:COUNTRY,
CURRENCY =:CURRENCY
where
COUNTRY =:OLD_COUNTRY
В приведенном запросе вместо значений указаны параметры, названия которых совпадают с названиями полей редактируемой таблицы. Это означает, что при изменении содержимого полей записи рассматриваемый компонент автоматически установит значения всех параметров через текущие значения полей или не-
Глава 15. Технология InterBase Express 439
которым другим образом. Префикс old_ в названии параметра означает, что в параметр будет подставлено старое содержимое поля до его изменения пользователем.
Разработчик должен указать, каким именно образом происходит определение параметров. К примеру, возможный вариант вызова оператора UPDATE с заданием параметров в обработчике события нажатия кнопки может иметь следующий вид:
procedure TForml.ButtonlClick(Sender: TObject); begin {изменение записи} with IBDataSetl do begin
Edit;
FieldByName('COUNTRY').AsString:= Editl.Text;
FieldByName('CURRENCY').AsString:= trim(FieldByName('CURRENCY').AsString);
Post;
end;
end;
Как видно из приведенного примера, вызов оператора UPDATE осуществляется с помощью метода Edit класса TiBDataSet. А именно, путем вызова метода Edit выполняется подготовка буфера текущей записи для редактирования, с помощью метода FieldByName задаются значения параметров оператора UPDATE и тем самым изменяются значения полей. С помощью метода Post осуществляется сохранение внесенных изменений в базе данных на сервере.
Для вставки и удаления записей в используемом нами классе TiBDataSetl служат методы insert и Delete соответственно. Для запросов, указываемых в свойствах insertSQL и DeleteSQL, задается аналогичная последовательность действий.
Рассмотренные нами запросы для компонента iBDataSet называют динамическими или "живыми" (live query).
Важным достоинством рассматриваемого компонента является то, что после выполнения любого действия по редактированию набора данных он выполняет запрос, указанный в свойстве Ref reshSQL. Этот запрос выполняет возвращение из базы данных одной — текущей записи и предназначен для обновления полей этой записи после внесенных изменений. Для нашего примера в свойстве Ref reshSQL должен быть следующий код:
Select
COUNTRY, CURRENCY
440
Часть III. Удаленные базы данных
from COUNTRY where
COUNTRY =:COUNTRY
Пояснить достоинство такого механизма можно следующим образом. Если в базе данных используются триггеры, модифицирующие значения полей базы данных, то внесенные в результате выполнения триггеров изменения пользователю не видны. Это означает, что для просмотра возможных изменений нужно выбрать нашу запись из базы данных с помощью оператора SELECT или полностью повторить выборку всех записей с помощью запроса из свойства SelectSQL. Такой вариант работы с измененными записями реализован при работе с помощью механизма BDE. Использование свойства Ref reshSQL в рассматриваемой технологии позволяет избежать необходимости повторной выборки записей всего набора данных.
Для автоматизации построения модифицирующих запросов, т. е. задания свойств ModifySQL, InsertSQL, DeleteSQL и RefreshSQL компонента IBDataSet, служит редактор. Вызов редактора выполняется с помощью команды Dalascl Editor контекстного меню компонента IBDataSet. Причем делается это после того, как задано его свойство SelectSQL.
На вкладке Options окна редактора модифицирующих запросов (рис. 15.4) выполняется выбор таблицы из списка Table Name. Далее с помощью кнопки Get Table Fields осуществляется формирование списков Key Fields и Update Fields. В списке Key Fields нужно выделить ключевые поля, на основе которых будет задаваться условие WHERE в создаваемых запросах. Если в выбранной таблице ключевые поля существуют, то для их выделения нужно нажать кнопку Select Primary Keys.
Глава 15. Технология InterBase Express
441
Выделение полей, для которых допускается редактирование, выполняется с помощью списка Update Fields. В состав этого списка нельзя включать вычисляемые поля, поскольку их содержимое редактировать не допускается.
Нажатие кнопки Generate SQL вызывает генерацию запросов. На вкладке SQL окна редактора отображаются тексты автоматически сгенерированных модифицирующих запросов, т. е. значения свойств ModifySQL, insertSQL, DeleteSQL и RefreshSQL компонента iBDataSet.
В компоненте IBDataSet реализованы обработчики трех событий:
property DatabaseDisconnected: TNotifyEvent; property DatabaseDisconnecting: TNotifyEvent; property DatabaseFree: TNotifyEvent;
Соответствующие события возникают после отключения БД, во время отключения БД и после высвобождения памяти компонентом соединения соответственно.
Компонент IBSQL
Компонент ibsql обеспечивает объект для выполнения SQL-запроса с минимальными накладными расходами. Так, для каждого запроса к набору данных, заданного в компоненте TiBDataSet, формируется объект tibsql. Рассматриваемый компонент получает набор данных в виде однонаправленного курсора и не обеспечивает навигацию по набору данных. Компонент ibsql не имеет локального буфера для набора данных и несовместим с визуальными компонентами.
Рассмотрим основные отличия компонента ibsql от его аналогов для технологий BDE, dbExpress и ADO Express.
Список имен параметров запроса создает свойство GenerateParamNames типа Boolean, план запроса содержит свойство Plan типа string.
Число возвращенных после выполнения запроса записей содержит свойство
RecordCount типа Integer.
Число записей, обработанных SQL-операторами insert, delete или update, содержит СВОЙСТВО RowsAf f ected типа Integer.
При работе приложения для баз данных зачастую полезно знать состояние набора данных. С этой целью при открытии запроса могут быть использованы следующие методы вызова исключений:
□ checkdosed; — если набор данных не закрыт;
□ checkOpen; — если набор данных не открыт;
□ CneckValidStatement; — если запрос синтаксически неправилен.
Выскажем короткое соображение по тому, в каких случаях предпочтительно использовать компонент ibsql. Для примера можно отметить вариант приложе-
442
Часть III. Удаленные базы данных
ния, в котором требуется выполнять массовую вставку записей в базу данных и при этом нет необходимости отображать вставляемые записи в пользовательских компонентах. В этом случае целесообразно использовать компонент ibsql, поскольку он не буферизует записи в отличие от iBDataSet. Тем самым мы достигаем более быстрой работы приложения.
Пример приложения
Рассмотрим пример приложения (рис. 15.5), построенного с использованием компонентов InterBase Express: IBDataSet, iBDataBase, iBTransaction, DataSource и нескольких вспомогательных компонентов DBEdit, DBGrid и Button.
Рис. 15.5. Вид формы при выполнении приложения
В примере демонстрируется возможность выборки, изменения, вставки и удаления записей БД, отображаемой с помощью компонента DBGrid.
Код модуля формы unitiDataSet для решения поставленной задачи имеет вид:
unit UnitiDataSet; interface
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, DB, Grids, DBGrids, IBCustomDataSet, IBDatabase, StdCtrls;
Глава 15. Технология InterBase Express 443
type
TForml = class(TForm)
iBDatabasel: TIBDatabase;
IBTransactionl: TIBTransaction;
iBDataSetl: TIBDataSet;
DBGridl: TDBGrid;
DataSourcel: TDataSource;
Editl: TEdit;
Labell: TLabel;
Edit2: TEdit;
Label2: TLabel;
Buttonl: TButton;
Button2: TButton;
Button3: TButton;
Button4: TButton;
Button5: TButton;
procedure Button2Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
procedure ButtonlClick(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Button5Click(Sender: TObject); private
{ Private declarations } public
{ Public declarations } end;
var
Forml: TForml;
implementation
{$R *.dfm}
procedure TForml.Button2Click(Sender: TObject); begin {вставка записи} with IBDataSetl do begin
Insert;
FieldByName('COUNTRY').AsString:= Editl.Text;
FieldByName('CURRENCY').AsString:= Edit2.Text;
444
Часть III. Удаленные базы данных
Post; end; end;
procedure TForml.Button4Click(Sender: TObject); begin {выборка записей}
iBDataSetl.Active:= False;
iBDataSetl.Active: = True; end;
procedure TForml.ButtonlClick(Sender: TObject); begin {изменение записи} with IBDataSetl do begin
Edit;
FieldByName('COUNTRY').AsString: = Editl.Text;
FieldByName('CURRENCY').AsString:= trim(FieldByName('CURRENCY').AsString);
Post;
end;
end;
procedure TForml.Button3Click(Sender: TObject); begin {удаление записи}
IBDataSetl.Delete; end;
procedure TForml.Button5Click(Sender: TObject); begin {выход}
IBDataSetl.Active:= False;
Forml.Close; end; end.
В обработчике события нажатия кнопки Button4 (с заголовком Выбрать) компонент IBDataSetl устанавливается активным, тем самым выполняется запрос на выборку всех записей (свойство Select SQL).
В обработчике события нажатия кнопки Buttonl (с заголовком Изменить) новое значение поля с именем ' COUNTRY' берется из свойства Editl. Text, в то время
Глава 15. Технология InterBase Express
445
как новое значение поля с именем 'currency' определяется как результат редактирования этого же поля.
В обработчике события нажатия кнопки Button2 (с заголовком Вставить) с помощью метода insert выполняется запрос из свойства insertSQL на вставку записи в набор данных, здесь же задаются значения параметров запроса. Имена полей для вставляемой записи берутся из свойств Editl.Text и Edit2.Text редакторов.
В обработчике события нажатия кнопки Button3 (с заголовком Удалить) с помощью метода Delete выполняется запрос из свойства DeleteSQL на удаление текущей записи из набора данных.
Глава 16
Инструментыдляработы