Шрифт:
DEFAULT 'F' NOT NULL
CHECK (VALUE IN ('F', 'T'))
CREATE DOMAIN TBOOLEAN_INT AS INTEGER
DEFAULT 0 NOT NULL
CHECK (VALUE IN (0, 1))
При использовании любой библиотеки компонент для доступа к InterBase оба способа совершенно равноценны, поскольку для полей, созданных с такими доменами, в приложении все равно не создаются Boolean-поля. То есть если мы добавим некоторое логическое поле к нашей таблице:
ALTER TABLE "Categories" ADD IS_ACTIVE TBOOLEAN_INT
NOT NULL
А потом, используя, например, компоненты IBX, сделаем выборку при помощи компонента TIBDataSet:
SELECT "Categories"."Name", "Categories".IS_ACTIVE
FROM "Categories"
то в результате компонент создаст два внутренних компонента для полей:
* TIBStringField для поля "Name" и
* TmtergerField для поля "IS_ACTIVE"
Последнее совершенно верно, поскольку формально поле "IS_ACTIVE" не является логическим. Таким образом, все визуальные компоненты типа TDBGnd и его расширенные аналоги от сторонних производителей не будут обрабатывать данное поле так, как нам бы хотелось. Например, если даже компонент умеет рисовать "галочки" для Boolean-полей, значения которых равно True, то поскольку он будет "видеть" всего лишь целочисленное поле, то и выводить он будет "0" и "1" Разумеется, если мы напишем соответствующие обработчики событий, то сможем добиться более или менее сносного отображения логических величин для поля TIntergerField, однако FIBPlus предоставляет гораздо более простое и качественное решение
Фактически оно состоит только в том, что нам необходимо добавить ключ 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,