Чтение онлайн

ЖАНРЫ

Мир InterBase. Архитектура, администрирование и разработка приложений баз данных в InterBase/FireBird/Yaffil

Востриков С М

Шрифт:

Фактически оно состоит только в том, что нам необходимо добавить ключ poUseBooleanField в свойстве PrepareOptions (рис. 2.60).

Рис 2.60. Использование PrepareOptions для эмуляции Boolean—полей

После этого поля, созданные на основе целочисленного домена, в названии которого присутствует слово "boolean", будут считать логическими, и для них будут создаваться

экземпляры TFIBBooleanField. Данный класс является прямым потомком класса TBooleanField и является полноценным логическим полем Любые визуальные компоненты для отображения данных будут работать с такими полями как с логическими, т. е. используя свойство AsBoolean. Вам же не придется писать для этого никакой дополнительный код.

Поддержка array-полей. Пример использования TpFIBUpdateObject и TDataSetContainer

InterBase с самых ранних версий позволял описывать в таблицах многомерные поля-массивы, делая хранение специализированных данных максимально удобным. Вы наверняка согласитесь, что матриц) проще всего хранить и обрабатывать в виде матрицы, а не раскладывать ее по отдельным полям и даже таблицам из-за ограничений реляционной модели Тем не менее поскольку array- поля не поддерживаются стандартом SQL, то и работа с такими полями на уровне SQL-запросов крайне затруднена. Фактически вы можете использовать массивы только поэлементно и только в операциях чтения Чтобы изменить значения array-поля, необходимо использовать специальные команды InterBase API. FIBPlus позволяет обойтись без подобных сложностей, взяв на себя всю рутину, связанную с array-полями

Мы продемонстрируем, как работать с array-полями при помощи FIBPlus на примере DemoArray5, входящем в стандартную поставку FIBPlus. Пример демонстрирует два варианта использования array-полей Первый способ позволяет редактировать array-поле при помощи специальных методов ArrayFieldValue и SetAiiayValue и работать с таким полем как с единой структурой (рис 2 6П

Рис 2.61. Внешний вид формы примера DemoArrayS Первый вариант использования array—полей

Рассмотрим запросы, заданные в соответствующих свойствах ArrayDataSet:

SeleetSQL

SELECT

JOB JOB_CODE,

JOB.JOB_GRADE,

JOB.JOB_COUNTRY,

JOB.JOB_TITLE,

JOB MIN_SALARY,

JOB.MAX_SALARY,

JOB.JOB_REQUIREMENT,

JOB.LANGUAGE_REQ

FROM

JOB JOB

ORDER BY 1,2,3

UpdateSQL:

UPDATE JOB SET

JOB_CODE = ?JOB_CODE,

JOB_GRADE = ?JOB_GRADE,

JOB_COUNTRY = ?JOB_COUNTRY,

JOB_TITLE = ?JOB_TITLE,

MIN_SALARY = ?MIN_SALARY,

MAX_SALARY = ?MAX_SALARY,

JOB_REQUIREMENT = ?JOB_REQUIREMENT,

JOB.LANGUAGE_REQ= ?LANGUAGE_REQ WHERE

JOB_CODE = ?OLD_JOB_CODE

and JOB_GRADE = ?OLD_JOB_GRADE

and JOB_COUNTRY = ?OLD_JOB_COUNTRY

InsertSQL

INSERT INTO JOB(

JOB_CODE,

JOB_GRADE,

JOB_COUNTRY,

JOB_TITLE,

MIN_SALARY,

MAX_SALARY,

JOB_REQUIREMENT,

JOB.LANGUAGE_REQ

)

VALUES(

?JOB_CODE,

?JOB_GRADE,

?JOB_COUNTRY,

?JOB_TITLE,

?MIN_SALARY,

?MAX_SALARY,

?JOB_REQUIREMENT,

?LANGUAGE_REQ

)

DeleteSQL:

DELETE FROM JOB

WHERE

J03_CODE = ? OLD_JOB_CODE

and JOB_GRADE = ?OLD_JOB_GRADE

and JOB_COUNTRY = ?OLD_JOB_COUNTRY

RefreshSQL:

SELECT

JOB.JOB_CODE,

JOB.JOB_GRADE,

JOB.JOB_COUNTRY,

JOB.JOB_TITLE,

JOB.MIN_SALARY,

JOB.MAX_SALARY,

JOB.JOB_REQUIREMENT,

JOB.LANGUAGE_REQ

FROM

JOB JOB

WHERE

(

JOB.JOB_CODE = ?OLD_JOB_CODE

and JOB.JOB_GRADE = ?OLD_JOB_GRADE

and JOB.JOB_COUNTRY = ?OLD_JOB_COUNTRY

)

Поле LANGUAGE_REQ

является массивом (LANGUAGE_REQ VARCHAR(15) [1:5]) и, как видно из запросов, обрабатывается целиком, а не поэлементно. С одной стороны это удобно, но не позволяет использовать для редактирования таких полей специализированные визуальные компоненты типа TDBGrid. Если мы используем array-поля для хранения значительных массивов данных, мы в любом случае будем использовать "ручную" обработку данных, не прибегая к помощи визуальных компонент. Однако для наглядности примера мы позволим редактировать элементы массива в компонентах TEdit.

Фактически нам понадобится написать только два основных обработчика для событий: BeforePost и OnPostError

procedure TForml.ArrayDataSetBeforePost(DataSet: TDataSet);

begin

with ArrayDataSet do begin

SetArrayValue(FieldByName('LANGUAGE_REQ'),

VarArrayOf([

Editl.Text,

Edit2.Text,

Edit3.Text,

Edit4.Text,

Edits.Text

]) ) ;

end;

end;

procedure TForml.ArrayDataSetPostError(DataSet: TDataSet;

E: EDatabaseError; var Action: TDataAction);

begin

Action := daAbort;

MessageDlg('Error!', mtError, [mbOk], 0);

ArrayDataSet.Refresh;

end;

Метод SetArrayValue позволяет задать все элементы поля в виде массива. Важным моментом является обработчик ошибки ArrayDataSetPostError В случае неудачной операции Update или Insert необходимо восстанавливать внутренний идентификатор массива у редактируемой записи. Это правило диктуется функциями InterBase API, и мы должны их придерживаться. Для восстановления идентификатора необходимо получить значения полей текущей записи заново, что и делается при помощи явного вызова метода Refresh.

Для автоматического заполнения визуальных компонентов значениями элементов массива мы можем написать обработчик события AfterScroll:

procedure TForml.ArrayDataSetAfterScroll(DataSet: TDataSet);

var v: Variant;

begin

with ArrayDataSet do try

FInShowArrays := true;

v := ArrayFieldValue(FieldByName('LANGUAGE_REQ'));

Editl.Text := VarToStr(v[l]);

Edit2.Text := VarToStr(v[2]);

Edit3.Text := VarToStr(v[3]);

Edit4.Text := VarToStr(v[4]);

EditS.Text := VarToStr(v[5]);

finally

FInShowArrays:=false;

end;

end;

Флаг FInShowArrays используется в примере для того, чтобы не включать режим редактирования записи при обычной навигации.

Рекомендуется иметь под руками полный текст примера, который доступен на сайтеВ книге мы указываем только те части примера, которые имеют непосредственное и наибольшее значение для работ с array-полями. Однако без полного текста некоторые части исходного текста могут показаться не до конца наглядными.

Поделиться с друзьями: