«Краткое оглавление КРАТКОЕ ОГЛАВЛЕНИЕ 1 ПОДРОБНОЕ ОГЛАВЛЕНИЕ 4 ВВЕДЕНИЕ 17 Для кого предназначено настоящее руководство 17 История создания платформы 17 Платформа с открытым кодом 18 Обзор архитектуры 20 УСТАНОВКА И ...»
Например, Товар имеет несколько связанных таблиц-множеств: драг.
Tgdc_frmG Наследован от TgdcCreateableForm. Является базовым классом для всех Tgdc_frmMDH Наследован от Tgdc_frmG. Является базовым классом для сложных форм Tgdc_frmMDHGR Наследован от Tgdc_frmMDH. Отображает данные в двух гридах, Tgdc_frmMDHGRAccount Наследован от Tgdc_frmMDHGR. Содержит дополнительную панель с выпадающим списком счетов текущей рабочей организации. Используется Tgdc_frmMDVGR Наследован от Tgdc_frmMDH. Отображает данные в двух гридах, Tgdc_frmMDV Наследован от Tgdc_frmMDH. Предполагается вертикальное отображение Tgdc_frmMDVTree Наследован от Tgdc_frmMDV. Содержит дерево (для master-объекта) и Tgdc_frmSGR Наследован от Tgdc_frmG. Является базовым классом для простых форм просмотра. Содержит грид для отображения содержимого бизнес-объекта.
Tgdc_frmSGRAccount Наследован от Tgdc_frmSGR. Содержит дополнительную панель с выпадающим списком счетов текущей рабочей организации. Используется Используя данные классы, вы можете «с нуля» создать свою форму.
Существуют так называемые стандартные классы форм, которые «зашиты» в программу. Все они наследованы от вышеперечисленных классов. Например, форма для отображения справочника ТМЦ – экземпляр класса Tgdc_frmMainGood. Вы можете изменять поведение стандартных форм за счет перекрытия методов и событий. Создать форму, наследуясь от стандартного класса в платформе Гедымине, невозможно. Как мы уже знаем из главы 6 о бизнес-объектах, прямое наследование в Гедымине не реализовано. Но этот пробел можно обойти за счет введения подтипа. Понятие подтипа для формы напрямую связано с бизнес-объектом. Расширяя стандартный бизнес-объект пользовательским подтипом вы автоматически получаете все его формы (для просмотра и редактирования) с тем же подтипом, а следовательно можете вносить изменения, которые будут характерны только для конкретного подтипа.
База данных В данной главе будет рассмотрена база данных, поставляемая с платформой Гедымин, ее объекты, даны их основные определения. Также вы сможете ознакомиться с механизмами изменения структуры базы данных, узнаете об ограничениях при работе с БД, заложенных в платформу Гедымин, и о том, как их обойти.
База данных состоит из различных объектов, таких как таблицы, представления (в некоторой литературе упоминаются как проекции), домены, хранимые процедуры, триггеры, индексы, ограничения (в данном случае имеются ввиду ограничения, накладываемые на данные в таблицах), генераторы, пользовательские функции (еще называют udf-функции, сокращение от английского User Defined Functions). Объекты базы данных содержат всю информацию о ее структуре и данных. Объекты базы данных также упоминаются как метаданные.
Для управления базой данных Interbase используется язык структурированных запросов SQL. SQL – это сокращение для Structured Query Language.
Если вы берете «голую» инсталляцию Гедымина (т.е. инсталляцию, которая включает в себя только платформу без настроек), то в ее пакете будет так называемая эталонная база данных. Эталонная база данных содержит только необходимые для начальной работы объекты, т.е. ее структура является общей частью для всех баз данных, предназначенных для работы с Гедымином. Настроенная база данных будет содержать кроме общих объектов еще и пользовательские. Пользовательские объекты БД имеют в своем наименовании префикс USR$. Такие объекты создаются посредством использования платформы Гедымин. Скажем также, что системные объекты БД Interbase имеют префикс RDB$. Объекты базы данных, не имеющие пользовательского и системного префиксов, будем называть стандартными.
Конечно, нарастить структуру БД можно и используя сторонние утилиты, но в этом случае вы рискуете столкнуться с некорректной работой платформы, особенно при переносе данных с одной базы на другую, при апгрейде (обновлении) базы данных и т.д. При использовании платформы Гедымин для изменения структуры БД помните, что вы можете изменять только пользовательские объекты БД. Изменение так называемых стандартных объектов может повлечь за собой некорректную работу, и поэтому непосредственно из-под платформы оно заблокировано.
Любое изменение метаданных возможно только под администратором сервера Interbase. Обычно это пользователь SYSDBA с паролем masterkey, если вы не изменили пароль при инсталляции.
Администратор Гедымина (пользователь Administrator) по умолчанию является также администратором сервера. Если вы попытаетесь изменить метаданные под другим пользователем, то вам будет предложено ввести пароль администратора сервера Interbase.
Следующие главы будут посвящены пользовательским объектам базы данных, их видам, способам создания.
Версия структуры базы данных История изменений структуры базы данных хранится в таблице FIN_VERSIONINFO. Запись с наибольшим ID определяет текущий номер версии структуры базы данных.
Информация из данной таблицы используется утилитой обновления структуры базы данных MODIFY.EXE.
Просмотреть информацию о текущей версии структуры базы данных можно так же на вкладке «База данных», диалогового окна «О системе». Вызов данного окна производится из меню «Справка» главного окна Гедымина.
FIN_VERSIONINFO
На момент написания данной книги последняя запись в таблице FIN_VERSIONINFO содержала следующие данные:VersionString — 0000.0001.0000.0092;
ReleaseDate — 01.03.2005;
Comment — Sync triggers procedures changed.
Типы данных. Домены Типы данных – это базовые элементы любого языка программирования или сервера СУБД. Когда мы говорим о том, что в базе данных хранится какая-то информация, то осознаем, что эта информация хранится в упорядоченном виде. Данные обрабатываются, исходя из их типа. Тип данных является своего рода ограничителем; он указывает, что можно передавать объекту данного типа, а что нельзя.
Каждый тип данных имеет определенный набор операций, который можно выполнять над значениями данного типа. Interbase предоставляет следующий набор типов (более подробно о них можно узнать в документации Interbase):
INTEGER – целое число, длиной 4 байта.
SMALLINT – короткое целое число, длиной 2 байта.
FLOAT – вещественный тип с плавающей точкой. Точность данного типа недостаточна для хранения больших дробных значений. Особенно данный тип не рекомендуется использовать для хранения денежных величин – в переменных типа FLOAT очень быстро нарастают ошибки за DOUBLE PRECISION – вещественный тип с плавающей точкой двойной точности. Аналогичен FLOAT, за исключением того, что предоставляет наибольшую точность при округлении NUMERIC – вещественный тип с фиксированной точкой. Имеет разрядность 18 знаков, точность – от нуля до разрядности. Разрядность – это общее количество цифр в числе, точность – количество знаков после запятой.
DECIMAL – вещественный тип с фиксированной точкой. Аналогичен NUMERIC. Для хранения денежных величин рекомендуется использовать либо NUMERIC, либо DECIMAL.
Дублирование практически одинаковых типов объясняется тем, что в более ранних версиях Interbase они имели некоторые отличия, и были сохранены для совместимости версий.
DATE – хранит даты с точностью до дня. Диапазон возможных значений от 1 января 100 года н.э. до 29 февраля 32768 года.
TIME – хранит данные о времени с точностью до десятитысячной доли секунды. Диапазон возможных значений – от 00:00 до 23:59.9999.
TIMESTAMP – представляет собой комбинацию типов DATE и TIME, т.е. хранит и дату, и CHAR – предназначен для хранения текстовой информации. Максимальная длина – символов. Если длина заданного значения короче, чем длина типа, то текст дополняется в конце пробелами. Эти пробелы не играют роли при сравнении полей различных текстовых типов, но выводятся при отображении значения данного типа. Такое поведение было необходимо ранее, когда табличная информация выводилась в текстовом режиме. Дополнительные пробелы помогали выравнивать значения по колонкам. Теперь, когда информация выводится в графическом режиме использование данного типа не является целесообразным.
VARCHAR – аналогичен типу CHAR, за исключением того, то значение не дополняется пробелами до заданной длины. И, следовательно, данный тип экономит трафик сети. Также называется текстовым типом переменной длины.
BLOB – для хранения динамически расширяемых данных. Позволяет хранить такие данные, как картинки, музыку, видео, большие тексты переменной длины. Имеет подтипы: 0 – данные неопределенного типа, 1 – текстовые данные, 2 – данные в двоичном виде.
В символьных типах (CHAR, VARCHAR) следует обратить внимание на такие характеристики как:
CHARACTER SET – набор символов. Набор символов определяется для всей базы данных и используется по умолчанию для всех текстовых полей, если не переопределяется явно при создании поля. База данных Гедымина имеет CHARACTER SET равный WIN1251.
COLLATION ORDER – указание порядка сортировки в зависимости от национального языка.
Для русского языка используется PXW_CYRL в паре с CHARACTER SET WIN1251.
Некоторые рассматривают домены как пользовательское расширение типов на основе уже имеющихся.
Однако домен определяет не только тип данных, но и может дополнить его некоторыми ограничениями, весьма полезными для сохранения целостности.
В Гедымине при создании новых полей в таблице вы не сможете им указать явный тип: типизация полей происходит только через домен. Кроме того, в большинстве случаев, если домен не указан, но указан явный тип, Interbase создает сам новый домен с автоматическим (а следовательно не несущим смысловой нагрузки) названием.
Следующая таблица 8.1 содержит перечисление наиболее часто используемых стандартных для Гедымина доменов.
DINTKEY x Используется для определения ключевого целочисленного поля DFOREINGKEY Целочисленный тип, используется для указания того, что поле DMASTERKEY x Целочисленный тип, используется для указания ссылки на таблицу
INTEGER
DINTEGER_NOTNULL x Целое число, данные данного типа не могут содержать NULL.
INTEGER
DOUBLE PRECISION
VARCHAR(60) может быть пустым. Используется обычно для обязательного DTEXTx (x – число) Текстовое значение переменной длины не более x символов. Может DPOSITIVE Дробное число с разрядностью 15 и точностью 8. Используется для NUMERIC(15, 8) хранения положительных чисел или чисел равных нулю.DCURRENCY Дробное число с разрядностью 15и точностью 4. Используется для DQUANTITY Дробное число с разрядностью 15и точностью 4. Используется для DBOOLEAN Логический тип. Т.к. Interbase напрямую не поддерживает DBOOLEAN_NOTNULL x Аналогичен домену DBOOLEAN, за исключением того, что может DSECURITY x Дескриптор безопасности. Используется для указания прав доступа DATE DDATE_NOTNULL х Домен для хранения даты. Не может быть пустым.
DATE TIME DTIME_NOTNULL х Домен для хранения времени. Не может быть пустым.
TIME
TIMESTAMP
DTIMESTAMP_NOTNULL х Домен для хранения даты и времени. Не может быть пустым.
TIMESTAMP
DBLOBTEXT Представляет собой текстовый BLOB для хранения текстов DDOCUMENTDATE х Дата документа. Обязательна для заполнения.DDOCUMENTNUMBER х Номер документа. Обязателен для заполнения. Является текстовым DDESCRIPTION Представляет собой текстовый BLOB для хранения текстов Таблица 0. В данной таблице перечислены далеко не все домены. Но даже среди перечисленных вы наверняка заметили дублирование типов, которые они описывают. По сути домены используются не только для определения типа и накладываемых на него ограничений. Название домена играет информационную роль. Кроме того, при изменении некоторых визуальных характеристик домена можно менять эти характеристики и у полей, которым сопоставлен данный домен. Как это сделать мы узнаем ниже.
Создание домена в системе Гедымин Бизнес-классом, отвечающим за работу с доменами, является класс TgdcField. Чтобы создать новый домен в системе Гедымин, необходимо выбрать в исследователе пункт Сервис \ Атрибуты \ Домены.
Перед вами появится форма просмотра доменов. Т.к. создание домена (как впрочем и любого объекта БД) – это изменение структуры базы данных, то делать эту операцию дозволено только администраторам сервера Interbase.
Итак, при добавлении нового объекта на экране появится мастер для добавления доменов. На первой его закладке вам будет предложено ввести название на английском языке, локализованное название (которое видит пользователь) на русском, и описание (смотрите рисунок 8.1). При вводе названия домена на английском вам не обязательно самим указывать префикс USR$. Если вы не указали его, то Гедымин добавит префикс при сохранении объекта БД.
Рисунок 0. Закладка «Тип данных» предоставляет пользователю возможность выбрать тип, на основе которого будет создан домен, добавить ограничения и значение по умолчанию. Рассмотрим ее поподробнее. Итак, мы можем создать следующие типы данных:
Строковый – переменной и постоянной длины. При этом вам необходимо указать максимальную длину. Если вы ходите хранить в поле информацию с использованием национальных символов, то желательно указать символьную кодировку и сличение.
Числовой – здесь вам необходимо указать, какое число вы будете хранить: короткое целое, длинное целое, дробное с плавающей запятой, дробное с фиксированной запятой. Для дробного числа с фиксированной запятой нужно указать разрядность и количество цифр для дроби Временной – дата, время или дата и время.
Двоичный – этот тип создается на базе BLOB-а. Вы можете создать строковое поле (т.е.
текстовый BLOB), для него желательно указать символьную кодировку, или произвольный BLOB для хранения картинок и другой информации.
Ссылка – один из наиболее сложных доменов. Создает целочисленное поле, которое является внешней ссылкой на другую таблицу. При этом вам необходимо указать таблицу, на первичный ключ которой будет ссылаться это поле, также поле для отображения из этой таблицы (используется в выпадающих списках, при формировании запроса парсером). Это поле необходимо для того чтобы пользователь мог видеть, что конкретно он выбирает для хранения в поле-ссылке, т.к. целочисленное значение ключа содержит весьма скромную информацию о записи. Также вы можете указать условие, по которому будут фильтроваться записи из таблицы, на которую создана ссылка. Это условие будет использоваться только в выпадающих списках.
Не должно содержать алиасов. Кроме всего прочего, при создании поля с доменом-ссылкой для таблицы сразу создается внешний ключ. Таким образом, через домен, обходится одно из ограничений Гедымина – нельзя создавать внешние ключи напрямую.
Множество – по набору параметров очень похож на тип Ссылка. Только, если для типа Ссылка создается целочисленное поле с внешним ключом на другую таблицу, то в случае множества создаваемое поле несет информационную нагрузку больше для внутреннего анализатора структуры БД. Создание поля с доменом Множество говорит Гедымину, что необходимо создать промежуточную таблицу-множество. Первичный ключ в данной таблице будет состоять из двух ключевых полей: поле-ссылка на таблицу, в которой создано поле-множество, и поле-ссылка на таблицу, которая указывается в параметрах домена-множества. Удаление поля-множества влечет за собой удаление таблицы-множества. Таблицы-множества имеют префикс USR$CROSS.
Кроме уже известных нам параметров «Ссылка на таблицу», «Поле для отображения», «Условие выбора значений» домен типа Множество имеет такие параметры, как «Множество с текстовым полем» (указывает, что создаваемое поле-множество будет текстовым, если этот параметр не указывать, то создастся поле с типом короткое целое) и «Длина поля» (данный параметр работает в паре с предыдущим, содержит длину текстового поля). Также необходимо помнить, что при выборе текстового типа вы можете указать кодировку и сличение. Текстовый тип позволяет заполнять поле-множество указанными значениями поля для отображения через пробел. Заполнение этого поля происходит на триггере, который создается вместе с полеммножеством. Таким образом пользователь даже при помощи грида может увидеть, какие записи другой таблицы соответствуют текущей. При указании целочисленного типа просмотреть какие записи соответствуют текущей можно будет только через диалог редактирования записи.
Перечисление – данный тип представляет собой перечисление возможных символов, которые в качестве значения может принимать поле. Каждому значению соответствует уникальное наименование, которое должно содержать краткую характеристику значения. При работе с типом Перечисление пользователь работает со списком наименований, а уже система сама подставляет в поле необходимое значение.
Также на закладке «Тип данных» есть раздел по контролю за содержимым поля. Этот раздел содержит три пункта:
Поле обязательно должно быть заполнено – указывает, что поле не может содержать NULLзначения. О использовании NULL-значений читайте ниже.
Значение по умолчанию – здесь указывается значение по умолчанию, которое будет принимать поле при добавлении новой записи (если при описании поля не будет указано иное значение по Ограничение – содержит правила по ограничению содержимого поля. Например, при создании логического поля на базе короткого целого типа используется ограничение, которое указывает, что из всего множества коротких целых чисел данный тип может использовать только 0 и 1.
Закладку «Тип данных» вы можете увидеть на рисунке 8.2.
Рисунок 0. Нам остается рассмотреть последнюю закладку «Визуальные» (рисунок 8.3), которая содержит визуальные настройки для домена. Эти настройки по умолчанию устанавливаются для полей, создаваемых с этим доменом. Итак, на этой закладке мы имеем следующие пункты:
Ширина поля при отображении – содержит визуальную ширину поля в пикселях, т.е., попросту говоря, ширину визуального элемента отображения, используемого для отображения / редактирования поля с данным доменом.
Рисунок 0. Поле является видимым по умолчанию – указывает, что поле по умолчанию отображается в гриде. Наверняка вы согласитесь, что пользователю необязательно видеть ключевые поля, т.к.
его скорее будет интересовать текстовое их представление. Для таких полей данный признак можно не устанавливать.
Запретить редактирование поля – указывает, что поле не редактируется пользователем вручную. Такие поля заполняются системой на триггере или на каком-либо событии в скрипте.
Используются по большей части для содержания признаков принадлежности записей к какойнибудь конкретной группе.
Формат вывода – указывает формат, в котором будут отображаться данные в колонке грида.
Для указания формата используется маска, принятая в Делфи (смотрите Таблица 0.2).
Символ Описание ! Данный символ означает, что дополнительные символы представлены в тексте как ведущие пробелы, в обратном случае – как замыкающие пробелы.
> Означает, что все символы, следующие за ним, будут в верхнем регистре, пока не закончится маска, или пока не встретится символ.
Если эти два символа встречаются в маске вместе, то регистр вводимых символов не \ Означает, что следующий за ним символ – это буквенный символ. Используйте его для вывода символов, используемых в формате маски.
L Означает, что только буква может быть на данной позиции. Для Соединенных Штатов это AZ, a-z.
l Разрешает ввести только букву на данной позиции, но не требует ее обязательного ввода.
A Означает, что только буква или цифра может быть на данной позиции. Для Соединенных a Разрешает ввести только букву или цифру на данной позиции, но не требует ее обязательного C Требует ввода любого символа на данной позиции.
c Позволяет ввести любой символ на данной позиции, но не требует его ввода.
0 Требует ввода цифры на данной позиции.
9 Позволяет ввести цифру на данной позиции, но не требует ее ввода.
# Позволяет ввести цифру или знак плюса или минуса на данной позиции, но не требует его : Используется как разделитель для часов, минут и секунд при вводе времени. При этом берется символ из региональных настроек компьютера.
/ Используется как разделитель для месяца, дня и года при вводе даты. При этом берется символ из региональных настроек компьютера.
; Используется для разделения трех полей маски.
_ Данный символ автоматически вставляет пробел в текст. Когда пользователь водит символы в поле, курсор пропускает символ _.
Таблица 0. Бизнес-класс – используется только для полей-ссылок. При автоматическом создании окна диалога бизнес-объекта для всех полей ссылок на форму кладутся выпадающие списки. Данный бизнес-класс будет подставлен в качестве параметра в выпадающий список, таким образом обеспечив работу со связанным бизнес-объектом. Внимание: данный бизнес-класс должен быть логически связан с таблицей, на которую идет ссылка. Еще лучше, если ссылку вы делаете на базовую таблицу указанного бизнес-класса. Если вы не указали никакого класса, но ваш домен – ссылка, то внутренний настройщик форм сам подставит в выпадающий список наиболее подходящий бизнес-класс по указанной таблице (т.е. будет найден бизнес-класс, базовая таблица которого равна указанной, или указанная таблица ссылается на базовую).
Подтип класса – используется в паре с предыдущим параметром. Содержит подтип класса, наиболее точно характеризующий связанный с нашим доменом-ссылкой объект.
Выравнивание – указывает как будет выводится информация в гриде: выровнено по левому краю, по правому или по центру.
Автоматическое обновление визуальных настроек полей, созданных с данным типом поля – данная опция говорит Гедымину, что делать при изменении характеристик домена. В отличие от других настроек она не хранится в базе, а работает как команда по окончанию редактирования домена. Может работать в трех режимах:
обновить настройки во всех полях – при подтверждении изменений для всех полей, созданных с данным доменом обновятся визуальные настройки в соответствии с указанными настройками домена. Например, вы забыли указать бизнес-класс при создании домена. Создали несколько полей с этим доменом и только тогда обнаружили оплошность. Достаточно отредактировать домен и установить данную опцию. Важно:
при этом у вас на редактирование должен быть открыт только домен. Настройки у открытых на редактирование полей не изменятся!
обновить настройки в полях, где настройки совпадают с настройками домена – аналогичен предыдущему пункту за исключением того, что настройки будут обновляться только в тех полях, где они остались такими же как у домена, т.е. вы не не обновлять настройки – ничего не делает с настройками полей при редактировании домена. Установлено по умолчанию. Т.к. изменять визуальные настройки полей по Здесь еще необходимо добавить, что при изменении домена нужно быть очень внимательным:
желательно не изменять домены, которые вы не создавали. Ваши изменения могут причинить ущерб уже существующей функциональности. Если вы не уверены, что ваши действия не причинят вреда, лучше создать свой аналогичный домен.
В уже созданном домене можно изменять все визуальные параметры, локализованные названия, а также (если это ссылка или множество) поле для отображения и условие.
Таблицы Гедымин использует реляционную СУБД. Помимо всего прочего это означает, что все данные в ней хранятся в виде таблиц. И, как мы уже знаем, бизнес-объект – это набор данных, основанный на запросе.
А в запросе участвуют таблицы.
Прежде дадим определение таблицы.
Таблица – это структура, состоящая из множества неупорядоченных горизонтальных строк (rows), каждая из которых содержит одинаковое количество вертикальных столбцов (colums). Пересечение отдельной строки и столбца называется полем (field), которое содержит специфическую информацию.
Многие принципы работы реляционной базы данных взяты из определений отношений (relations) между таблицами.
Одно из требований реляционной базы данных – это то, что каждая таблица должна содержать первичный ключ. Конечно, можно создать таблицу и без первичного ключа, но это может привести к проблеме идентификации записи, а следовательно, вы не сможете корректно обработать запись. Итак, повторяя уже сказанное, первичный ключ – важнейший объект базы данных, используемый для однозначной идентификации записи. Бизнес-объект поддерживает только простые первичные ключи, за исключением режима множества, когда поддерживается составной ключ.
Виды пользовательских таблиц Мы уже знаем, что пользовательские бизнес-объекты создаются на основе пользовательских таблиц.
Гедымин предлагает несколько видов таблиц, предназначенных для решения различных задач.
Простая таблица с идентификатором;
Таблица с идентификатором;
Таблица со ссылкой;
Простое дерево;
Интервальное дерево;
Каждый тип отличается от другого набором полей, триггерами, внешними ключами, хранимыми процедурами, создаваемых по умолчанию. И у всех этих типов есть одна общая черта: они все содержат ключевое поле ID с доменом DINTKEY (кроме таблицы-ссылки, которая создает для поля ID свой домен). Создать таблицу без полей нельзя.
Простая таблица с идентификатором Данный тип создает самый простой вид таблиц. Таблица с таким типом по умолчанию содержит одно поле ID с доменом DINTKEY, которое и является ключевым. Также для этой таблицы создается первичный ключ, и триггер, который заполняет ключевое поле при вставке новой записи. Таблицы подобного типа обычно используются для небольших справочников, которые будут хранить редко редактируемые записи (например, справочник назначений платежа). Бизнес-объект, созданный на основе этой таблицы имеет класс TgdcAttrUserDefined и подтип, равный английскому названию таблицы.
Таблица с идентификатором В отличие от предыдущего типа содержит также поля EDITORKEY (кто модифицировал), EDITIONDATE (когда модифицировал), DISABLED (отключено). На поле EDITORKEY создается внешний ключ на справочник контактов (в данном поле хранится ссылка не на пользователя, а на контактное лицо, который тот представляет). Кроме того, создаются два дополнительных триггера, которые перед вставкой записи и ее модификацией проверяют, указано ли контактное лицо, изменившее данные, и дата модификации. При отсутствии данной информации эти триггеры подставляют по умолчанию в качестве контакта администратора и в качестве даты модификации текущую дату. Данный тип таблиц используется уже для более сложных справочников, данные которых могут часто изменяться (для этого добавлено два поля для отслеживания изменений) и устаревать / становиться не актуальными (для этого используется поле DISABLED). Бизнес-объект, созданный на основе этой таблицы имеет класс TgdcAttrUserDefined и подтип, равный английскому названию таблицы.
Таблица со ссылкой Данная таблица также по умолчанию содержит всего одно поле ID. Но в отличие от простой таблицы с идентификатором, ее первичный ключ является одновременно и внешним ключом. Здесь идет реализация связи один-к-одному. При создании такой таблицы указывается главная таблица, на которую будет ссылаться создаваемая. Создается пользовательский домен-ссылка со ссылкой на главную таблицу, который используется в качестве типа для поля ID. Такие таблицы используются для расширения справочников какими-либо редко используемыми признаками. Вынесение подобных признаков в отдельную таблицу помогает экономить физическое пространство, занимаемое базой. Однако увлекаться подобными таблицами не стоит, т.к. их приходиться отдельно обрабатывать. Бизнес-объект, созданный на основе этой таблицы имеет класс TgdcAttrUserDefined и подтип, равный английскому названию таблицы. Но более логично для подобной таблицы использовать не отдельный бизнес-объект, а подключать ее в запрос к основному бизнес-объекту по мере необходимости. Например, среди стандартных таблиц можно выделить таблицу gd_companycode, которая хранит некоторые признаки организаций. Данная таблица не имеет собственного бизнес-объекта, но подключается в запрос к бизнесобъекту Организации.
Простое дерево Расширяет тип Таблица с идентификатором полем PARENT. Данное поле является ссылкой на собственное ключевое поле, следовательно, создается дополнительный внешний ключ. Таблицы подобного типа используются для организации структур небольшой вложенности. При очень большой вложенности вам будет тяжело извлечь все вложенные уровни по верхнему. Например, базовая таблица GD_COMMAND бизнес-объекта Исследователь является простым деревом. Бизнес-объект, созданный на основе этой таблицы имеет класс TgdcAttrUserDefinedTree и подтип, равный английскому названию таблицы.
Интервальное дерево В дополнение к предыдущему типу содержит также такие поля, как LB (левая граница, сокращение от английского Left Bounday) и RB (правая граница, сокращение от английского Right Boundary). Самый сложный тип пользовательских таблиц. Левая и правая границы используются для определения вложенных уровней для текущей записи. Для их заполнения создается три хранимые процедуры (с названиями USR$_P_CHLDCT_, USR$_P_EXLIM_, USR$_P_RESTR_), которые используются для пересчетов интервалов, специальные триггеры, которые вызывают пересчет интервалов через процедуры при изменении данных, и исключение USR$_E_TR_, возникающее при попытке зациклить ветки дерева. На поля LB, RB создаются индексы. Создание подобной таблицы требует переподключения к базе. Таблицы данного типа используются для создания сложных вложенных структур с большим уровнем вложенности. Например, весь справочник клиентов реализован при помощи интервального дерева GD_CONTACT. Использование правых и левых границ помогает просматривать все контакты, которые входят не только в текущую папку, но и во вложенные папки. Бизнес-объект, созданный на основе этой таблицы имеет класс TgdcAttrUserDefinedLBRBTree и подтип, равный английскому наименованию таблицы.
Если первые четыре типа достаточно понятны, то интервальное дерево требует особого внимания.
Рассмотрим его поподробнее.
Само название «Интервальное дерево» говорит нам о том, что работа с уровнями использует интервалы, при этом левая граница является началом интервала, а правая граница – окончанием. Самый верхний уровень дерева будет иметь наименьшую левую границу и наибольшую правую. Конечные узлы дерева, в которые никогда не входили никакие подуровни, будут иметь равные равные между собой правую и левую границы. Итак, что же означает интервал и его границы? Для простоты рассмотрим это на примере.
Предположим у нас есть папка «Организации», в которую вложены папки «ООО», «ОДО», «ИП». Все эти папки будут иметь родителем папку «Организации», т.е. в поле PARENT будет содержаться ключ папки «Организации». Пусть в каждой папке есть некий набор организаций. Мы имеем древовидную структуру, представленную на рисунке 8. Чтобы найти вложенные уровни по родителю, достаточно выполнить запрос вида:
SELECT * FROM gd_contact z WHERE z.parent = :parent Однако если нам необходимо просмотреть все вложенные уровни, то такого запроса будет не достаточно. В нашем примере, нам придется выполнить подобный запрос четыре раза: первый раз для того, чтобы найти все вложенные папки в папку «Организация», и три раза, чтобы найти все вложенные организации в каждую из трех папок.
Рис. 47 Иллюстрация интервального дерева.
Использование правых и левых границ позволяет просмотреть все вложенные уровни, используя один запрос. Необходимо сопоставить каждому элементу выборки пару чисел так, чтобы пара чисел вложенного уровня входила в интервал, образованный парой чисел родителя. В отношении нашего примера можно представить следующую таблицу 8.2.
ID PARENT LB RB NAME
(Идентификатор) (Идентификатор (Левая (Правая (Наименование) Таблица 0. И этой таблицы видно, что самый верхний уровень имеет достаточно большой интервал от 3000 до 6008, вложенные уровни – интервалы поменьше, а листья дерева – интервал равный единице (т.е. правая граница совпадает с левой). Имея подобную информацию, можно вытянуть все вложенные уровни для указанного посредством одного запроса:SELECT z.* FROM gd_contact z JOIN gd_contact c ON c.lb = z.rb WHERE c.id = :id Здесь в качестве параметра ID передается идентификатор узла, для которого мы будем выводить все вложенные уровни. Нестрогое сравнение правой и левой границ позволяет вывести и сам узел. Чтобы вывести только вложенные уровни необходимо в условии использовать строгое сравнение:
SELECT z.* FROM gd_contact z JOIN gd_contact c ON c.lb < z.lb AND c.rb > z.rb WHERE c.id = :id Как же формируются интервалы, ведь нам известно, что пользователь при вводе новой записи их не задает? На триггерах перед вставкой и изменением записи осуществляется пересчет границ. При этом чем больше вложенности имеет узел, тем больше запаса в интервале ему предоставляется (сравните интервалы для самого высокого уровня и вложенных уровней). Это необходимо, чтобы пересчет и обновление интервалов не происходил при каждом изменении данных, что может существенно замедлить работу. Для пересчета границ используются следующие хранимые процедуры:
USR$_P_CHLDCT_ - рекурсивно пробегается по всем вложенным уровням и проверяет их диапазоны. При необходимости присваивает новые значения границ.
Используется в процедуре USR$_P_RESTR_.
USR$_P_EXLIM_ - проверяет диапазон для вставки новой записи и раздвигает его, если он мал. Используется в триггерах.
USR$_P_RESTR_ - сжимает интервалы дерева.
Как мы видим в триггерах используется только одна процедура USR$_P_EXLIM_.
Другие две являются вспомогательными и могут использоваться для восстановления корректных интервалов после сбоев системы. При попытке зацикливания (например, при указании родителем собственного вложенного уровня) сработает внутренне исключение Interbase, и на экране появится сообщение:
Can not cycle tree branch!
Создание и редактирование таблиц средствами Гедымина Бизнес-классом, отвечающим за работу с таблицами, является класс TgdcTable. При этом для каждого вида таблиц идет свой бизнес-класс, наследованный от TgdcTable:
TgdcPrimeTable – отвечает за работу с простой таблицей с идентификатором;
TgdcSimpleTable – для работы с таблицей с идентификатором;
TgdcTableToTable – для работы с таблицей-ссылкой;
TgdcTreeTable – для работы с простым деревом;
TgdcLBRBTreeTable – для работы с интервальным деревом;
TgdcUnknownTable – для работы с множествами. Также этот тип возвращается для всех остальных стандартных таблиц.
Здесь необходимо различать бизнес-объекты для работы с таблицами и бизнес-объекты, построенные на основе пользовательских таблиц. Бизнес-объекты для работы с таблицами отвечают за изменение структуры таблиц. Бизнес-объекты, построенные на основе таблиц, отвечают за изменение данных в этих таблицах.
Чтобы создать новую таблицу в системе Гедымин, необходимо выбрать в исследователе пункт Сервис \ Атрибуты \ Таблицы. Перед вами появится форма просмотра таблиц. Создание таблицы также дозволено только администраторам сервера Interbase.
При добавлении новой таблицы вам будет предложено выбрать тип таблицы. С возможными типами мы ознакомились ранее. В соответствии с выбранным типом идет настройка первой закладки мастера.
Диалог создания / редактирования таблицы состоит из четырех закладок:
Закладка Таблица содержит следующие поля для заполнения:
Название таблицы на английском языке – собственно название таблицы. Если вы не укажете префикс USR$, то система сама добавит его. Максимальная длина названия – 31 символ (как впрочем и любого объекта БД), однако рекомендуется использовать названия не длиннее символов, т.к. они участвуют в формировании названий других объектов базы данных при обработке запросов бизнес-объекта парсером.
Локализованное название таблицы – название таблицы на национальном языке, понятное простому пользователю. Это название будет использовано в качестве наименования для отображения (функция бизнес-объекта GetDisplayName) при использовании данной таблицы как базовой для бизнес-объекта. Должно быть уникально в пределах базы.
Краткое название таблицы – сокращенный вариант локализованного названия таблицы.
Описание таблицы – содержит описание данных, которые будет хранить таблица.
Ветка для команды вызова в Исследователе – содержит ссылку на ветку исследователя, в которой будет содержаться ветка для вызова формы просмотра созданной таблицы. Т.е. мы указываем существующую ветку-родителя, а платформа сама создает в ней ветку для просмотра таблицы. Если этот параметр не указывать, то никакой ветки в исследователе создано не будет.
Ссылка на таблицу(связь один к одному) – этот параметр виден только для таблиц-ссылок.
Указывает главную таблицу, на которую будет ссылаться первичный ключ создаваемой таблицы. При этом у главной таблицы должен быть простой первичный ключ.
Поле для отображения(на английском) – текстовый необязательный параметр. Если ничего не указывать, то будет использовано поле для отображения (свойство бизнес-объекта GetListField) по умолчанию. Т.е. система сначала поищет, есть ли в таблице поле USR$NAME, если нет, то возьмет в качестве поля для отображения первое строковое поле, если строковых полей в таблице нет, то возьмет первое поле любого типа. Т.е. если вы хотите, чтобы в качестве поля для отображения у вас использовалось весьма конкретное поле, то укажите его название в «поле для отображения (на английском)». При этом, если в названии будет ошибка, то система просто проигнорирует данный параметр.
Поля для расширенного отображения (на английском через запятую) – текстовый необязательный параметр. Указывает какие поля для расширенного отображения вы хотите использовать для данной таблицы. Например, полем для отображения для таблицы GD_DOCUMENT является поле NUMBER. Однако один номер документа не несет достаточной информации. Желательно выводить также дату документа. Поэтому в данном параметре для таблицы GD_DOCUMENT можно указать DOCUMENTDATE. Теперь, если SQL-парсер найдет в запросе ссылку на таблицу GD_DOCUMENT, то он добавит в запрос не только поле для вывода номера документа, но и поле для вывода даты документа.
Соответствующий бизнес-класс – параметр заполняется системой Гедымин. Является информационным. Указывает пользователю, какой бизнес-класс представляет таблица.
Соответствующий подтип – работает в паре с предыдущим параметром. Указывает пользователю, какой подтип бизнес-класса представляет таблица. Для стандартных таблиц (без префикса USR$) будет всегда пустым.
Закладка Поля предлагает вам добавить / отредактировать / удалить поля в созданной таблице. При переходе на эту закладку в режиме добавления таблицы вы увидите, что поля, заданные по умолчанию, уже созданы. Эти поля вы не сможете удалить, т.к. их наличие определяет тип таблицы. Мастер для создания полей мы рассмотрим несколько позднее.
Закладка Триггеры доступна только при модификации уже существующей таблицы. Т.к. для создания триггера Гедымин уже должен знать, какие поля есть в таблице. Верхняя часть закладки представляет собой дерево, в котором перечислены триггеры. Отключенные триггеры выделяются серым цветом.
Панель посредине предоставляет пользователю возможность добавить / отредактировать / удалить триггер. Все эти действия определены только над пользовательскими триггерами. Нижняя часть закладки отображает тело триггера, на котором стоит курсор (смотри рисунок 8.5).
Рисунок 0. Закладка Индексы отображает созданные для текущей таблицы индексы, а также содержит панель с кнопками для создания / редактирования / удаления индекса. Диалог для модификации индекса будет рассмотрен несколько ниже.
В уже созданной таблице вы можете изменять параметры для локализации, указание полей для отображения, добавлять / изменять / удалять поля, триггеры, индексы.
Диалог для создания / изменения полей таблицы Поле таблицы – это также объект базы данных. Но понятие таблицы без полей невозможно, поэтому мы рассмотрим диалог для создания / изменения полей в главе, посвященной таблице.
Бизнес-классом для работы с полями таблицы является класс TgdcTableField. Если рассматривать поле как бизнес-объект, то сразу можно оговориться, что его мастер-объектом будет являться таблица. Т.е.
базовая таблица AT_RELATION_FILEDS бизнес-объекта Поле имеет ссылку RELATIONKEY с доменом DMASTERKEY на базовую таблицу AT_RELATIONS бизнес-объекта Таблица.
Диалог бизнес-объекта Поле можно вызвать и с диалога редактирования таблицы, и с формы просмотра таблиц и полей. Различие в вызове имеет некоторые отличия при создании полей. Если мы создаем поля из диалога редактирования таблицы, то они будут созданы не при закрытии диалога редактирования поля, а по завершении работы с таблицей вообще. И их создание может идти не в том порядке, в котором мы их описывали (поэтому через диалог редактирования таблиц запрещено создавать вычисляемые поля – они могут содержать ссылки на другие поля таблицы, которые будут созданы позже). При создании полей через форму просмотра, поле создается каждый раз при закрытии диалога редактирования поля (или нажатии на нем кнопки Новый). Это позволяет более точно задать порядок в котором будут созданы поля, но несколько замедляет работу, если вам необходимо добавить много полей.
Мастер Гедымина для создания полей имеет три закладки:
Закладка Общие содержит следующие параметры:
Таблица – нередактируемый параметр, указывает пользователю, для какой таблицы создается Название поля на английском языке – собственно название поля, длиной не более 31 символа.
Используется в запросах. Желательно не создавать поля с очень длинными названиями, т.к. их названия могут использоваться для формирования наименований других объектов БД.
Локализованное название – название поля на национальном языке. Содержит краткую характеристику поля.
Краткое название – укороченный вариант локализованного названия. Краткое название используется в качестве названия колонок грида на формах отображения.
Описание поля – подробная характеристика поля.
Тип поля – здесь вы можете указать домен или установить флаг вычисляемое поле. При выборе домена если у поля не указаны локализованные названия, то они подставляются из локализованных названий домена.
Not NULL – используется только при указании домена поля. Говорит о том, что поле не может быть пустым. Первоначально устанавливается из установок домена. Если домен имеет флаг Not NULL, то снять этот флаг у поля нельзя. Обратное возможно.
Значение по умолчанию – хранит значение подставляемое в поле при добавлении новой записи в таблицу. Первоначально устанавливается из установок домена. Недоступно, если поле вычисляемое.
Правило удаления – видимо только для поля-ссылки. Может принимать одно из четырех NO ACTION - запрещать удаление при удалении главной записи (т.е. вы не сможете удалить главную запись, пока на нее существует ссылка);
CASCADE - удалять, если удаляется главная запись (этот принцип используется в сложных документах – нет смысла удалять сначала все позиции документа, а только затем шапку, гораздо логичнее, чтобы при удалении шапки позиции удалялись SET NULL - устанавливать значение NULL (главная запись удалиться, а ссылки на нее SET DEFAULT - устанавливать значение по умолчанию (аналогично предыдущему, только вместо NULL на место ссылки будет установлено значение, которое задано для Выражение для вычисляемого поля на SQL – хранит выражение, по которому будет вычисляться значение поля. Доступно только если поле является вычисляемым.
Вычисляемое поле – это поле, значение которого вычисляется динамически. В выражении для вычисления значения поля могут участвовать поля текущей таблицы, SQL-функции, также, используя подзапрос, можно обратиться к полям другой таблицы. Для вычисляемого поля всегда создается системный домен.
Закладка Визуальные настройки первоначально заполняется из установок домена. Содержит следующие параметры:
Ширина поля при отображении Поле является видимым по умолчанию Запретить редактирование поля Выравнивание Бизнес-класс Расшифровку этих параметров можно посмотреть в пункте 8.1.1 «Создание домена в системе Гедымин».
Закладка Объекты содержит дерево доступных бизнес-объектов. В этом дереве птичками обозначены объекты, для которых данное поле будет видимым. если не обозначен ни один объект, поле будет видимым для всех. Видимость распространяется не только на объекты отмеченных классов, но и на объекты дочерних классов. Т.е. если отметить TgdcBase (по умолчанию именно он и отмечен), то поле будет видимым для всех.
Осталось только пояснить, что мы понимаем под видимостью полей в бизнес-объектах. Нам известно, что бизнес-объект – это набор данных, выборка и изменение которых идет посредством выполнения SQL-запросов. В данном случае видимость поля означает попадание его в SQL-запрос. Если поле не попадет в SelectSQL, то оно, естественно, не будет отображаться. Кто-нибудь спросит: «Во-первых, зачем прятать поле, если мы его создали; во-вторых, какое отношение к данному полю имеют все бизнесобъекты, если известно, что каждой таблице соответствует один бизнес-объект?» Ответ на эти два вопроса будет один: данная закладка предназначена, чтобы прятать пользовательские поля в объектах, для которых текущая таблица не является базовой. Дело в том, что SQL-парсер при обработке SQLзапроса вытягивает все пользовательские поля для всех таблиц, входящих в запрос. Например, вам необходимо для каждой компании отображать ее главный счет, следовательно вам нужно в запрос бизнес-объекта Организации добавить таблицу GD_COMPANYACCOUNT и выводить только одно ее поле ACCOUNT. Однако, если в таблице GD_COMPANYACCOUNT есть пользовательские поля, то SQL-парсер добавит их автоматически в SELECT-часть запроса для объекта Организации. Чтобы этого не произошло, для всех пользовательских полей таблицы GD_COMPANYACCOUNT необходимо указать, что они должны отображаться только для бизнес-объекта Расчетный счет (класс TgdcAccount).
Чтобы пользовательские поля не попадали в запрос, можно также использовать свойство бизнес-объекта SQLSetup.
Генераторы Генератор – это специфический объект базы данных. Употребляя слово «специфический» мы хотим сказать, что не все базы данных предоставляют механизм генераторов. В Interbase генераторы используются достаточно широко.
Мы уже говорили о первичных ключах таблиц, и о том, что чаще всего это простые целочисленные ключи. Как же обеспечить их уникальность? Можно каждый раз выполнять запрос к таблице и искать максимальное значение ее ключа и затем найденное значение увеличивать на единицу. Однако это неудобно, может быть ощутимо по времени, а также может вызвать конфликт, если другой пользователь работает с этой же таблицей при открытой транзакции на изменение. В данном случае генератор является достаточно удобным и быстрым средством.
Что же такое генератор? Генератор – это, попросту говоря, именованный счетчик. При этом приращение генератора работает на собственной внутренней транзакции. Т.е. вне зависимости от того, добавите вы запись в таблицу или откатите ее добавление, если вы уже успели затребовать новое значение из генератора, то он будет хранить это новое значение.
В основном генераторы используются в триггерах до вставки записи для присвоения нового значения ключа. Кто-то использует для каждой таблицы свой генератор, платформа Гедымин использует для всех таблиц один генератор GD_G_UNIQUE, что обеспечивает уникальность ключей в пределах базы.
Чтобы получить новое значение генератора через запрос, необходимо выполнить следующую инструкцию:
SELECT GEN_ID(gd_g_unique, 1) FROM rdb$database Функция GET_ID указывает SQL, что будет работа с генератором, первый параметр содержит название генератора, второй – шаг приращения. Если вторым параметром передать ноль, то запрос вернет текущее значение генератора.
В триггере же достаточно указать, что вы новому значению ключевого поля присваиваете результат от выполнения функции GEN_ID.
NEW.ID = GEN_ID(gd_g_unique, 1) В существующих триггерах вы можете увидеть, что при присвоении нового ключа используется еще один триггер GD_G_OFFSET. Этот генератор устарел, и уже нигде не используется. Вы можете смело его опускать.
Создать новый генератор средствами Гедымина нельзя, и бизнес-класса для него не существует.
Стандартные генераторы Ниже приводится список генераторов, поставляемых с эталонной базой данных.
Генератор Комментарий gd_g_attr_version Увеличивается каждый раз, когда происходит изменение структуры базы данных или изменяется информация в at_ таблицах. Вместо того, чтобы каждый раз при подключении к базе данных считывать ее структуру, Гедымин кэширует необходимую информацию, сохраняя ее на локальном жестком диске. Вместе с кэшированными данными сохраняется значение генератора gd_g_attr_version. При очередном подключении проверяется значение генератора из кэша и полученное из базы данных, если они совпадают, значит структура не изменялась и можно воспользоваться кэшем, если нет, то необходимо перечитать структуру базы данных.
gd_g_block Используется для блокировки периода. Если равен 0, то блокировка выключена. В случае, если блокировка включена, генератор хранит приведенную к целому числу gd_g_block_group Данный генератор хранит битовую маску групп пользователей на которых не распространяется блокировка периода. Используется только, если блокировка gd_g_dbid Уникальный идентификатор базы данных. Если равен 0, то при очередном подключении Гедымин сгенерирует новый идентификатор и запишет его в этот генератор. Значение генератора используется при формировании РУИДа записи.
Текущее значение идентификатора базы данных можно получить через свойство gd_g_functionch Аналогично генератору gd_g_attr_version, данный генератор используется для контроля актуальности кэша скрипт-функций. Увеличивается каждый раз, когда gd_g_offset На данный момент не используется. Значение 0.
gd_g_session_id Порядковый номер сессии. Увеличивается при каждом подключении к базе данных.
Текущий номер сессии можно получить через поле SessionID глобального объекта gd_g_triggercross При добавлении в пользовательскую таблицу поля типа множество в базе данных создается т.н. кросс таблица, которая содержит две ссылки: на таблицу, в которой добавлено поле-множество и на справочник, содержащий элементы множества.
Генератор gd_g_triggercross используется для обеспечения уникальности имени кросс таблицы, которое формируется как USR$CROSS, где — значение генератора. Увеличивается, каждый раз при создании очередной кросс gd_g_unique Используется для генерации уникального идентификатора записи. Начальное inv_g_balancenum Используется для визуальной организации выбора складских остатков.
Индексы Индексы – это механизм для улучшения быстродействия поиска данных. Индекс определяет столбцы которые могут быть использованы для эффективного поиска и сортировки в таблице. InterBase автоматически определят индексы для первичных и внешних ключей таблицы.
Существует достаточно распространенное мнение, что по индексированному полю поиск идет быстрее, чем по неиндексированному. Однако это не всегда так. Для небольших таблиц нет необходимости создавать индекс, т.к. запрос отработает быстрее, если переберет все записи, чем будет отбирать их по индексу. В случае маленькой таблицы при использовании индекса будет больше обращений к страницам базы данных, нежели при простом переборе.
Структура индексов - наиболее важный момент при проектировании структуры базы данных.
Эффективность оптимизации запросов в InterBase в огромной степени зависит от правильной структуры индексов. В большинстве случаев используется примерно следующий алгоритм создания индексов сначала определяются первичный ключ и уникальные индексы по тем полям, где необходимо исключить дублирование значений, потом создаются неуникальные индексы для внешних ссылок (foreign key) и для полей, по которым наиболее часто происходит поиск/сортировка. В большинстве случаев это работает. Однако надо иметь ввиду, что эффективность неуникальных индексов резко падает при большом количестве одинаковых величин в столбце и в результате наличие индекса в некоторых ситуациях может тормозить, а не ускорять выполнение запроса.
Не следует перегружать таблицу индексами, т.к. каждый индекс требует дополнительной памяти.
Interbase автоматически создает индексы для первичного ключа и внешних ключей (в отличие от некоторых других баз данных). При создании дополнительных индексов необходимо сначала проанализировать, по каким параметрам будет чаще идти поиск (возможно поиск записей будет идти по нескольким параметрам, тогда лучше создать один сложный индекс, чем несколько простых индексов).
Кроме того, если у вас на таблице есть несколько индексов, которые затрагивают одно и то же поле, то лучше проанализируйте вашу структуру еще раз. Возможно некоторые из этих индексов лишние.
Существует еще такое понятие, как статистика индексов. Статистика, показывает насколько у вас разные значения в поле таблицы, на основании которого у вас построен индекс. Считается она следующим образом:
Величина статистики индекса = 1 / Количество различных значений, содержащихся в данном поле таблицы.
Т.е., например, в таблице GD_CONTACT поле CONTACTTYPE может принимать значения от 0 до 5.
Если мы создадим индекс на это поле и внесем хотя бы по одной записи с каждым типом, то величина статистики будет 1 / 6 = 0,1666(6), что является не очень хорошим результатом. Здесь, однако, нужно учитывать, что статистика только в некоторых случаях (как в примере с GD_CONTACT и CONTACTTYPE) не будет сильно изменяться при добавлении данных. Чаще всего статистика индексов достаточно сильно зависит от создания новых записей.
Например, статистика индекса, созданного на первичный ключ, может быть равна 1, если у вас всего одна запись. Как вы понимаете, в данном случае использование индекса будет нецелесообразно. Однако, если мы добавим в таблицу 300 записей, то статистика изменится и станет равной 1 / 300 = 0,00333(3), и использование индекса в данном случае будет оправдано.
Теперь поговорим о том, какие механизмы для работы с индексами предоставляет Гедымин. Вы можете создавать / изменять / удалять пользовательские индексы, и в данном случае не иметь практически никаких ограничений. Но есть еще и так называемые стандартные индексы (здесь мы не затрагиваем индексов, создаваемых Interbase автоматически при добавлении первичных и внешних ключей).
Стандартные индексы можно сделать неактивными и оптимизатор запроса не будет их учитывать.
Операции над индексами можно производить из диалога редактирования таблицы. Существует также и форма просмотра индексов, представляющая собой форму с master-detail связью, где мастер-объект – это таблица, а детальный объект – это индекс. Изначально это форма не доступна из исследователя. Однако вы сами можете добавить эту ветку при желании. Для этого необходимо добавить новый пункт исследователя, выбрать переключатель «Бизнес-объект», в выпадающем списке выбрать класс TgdcIndex (бизнес-класс для работы с индексами).
При открытии формы просмотра индексов вам будет задан вопрос, синхронизировать ли индексы с базой данных. Как мы помним для ускорения часть данных кэшируется на локальном компьютере.
Синхронизация таких метаданных, как таблицы, домены, поля происходит достаточно быстро, а потому не требует подтверждения пользователя. Синхронизация же индексов иногда требует ощутимых временных затрат.
Итак, что представляет собой диалог редактирования индекса (смотрите Рис. 48 Диалоговое окно создания или изменения индекса):
Название индекса – собственно название индекса на английском языке. Не более 31 символа.
Желательно давать более менее осмысленные названия, которые бы говорили о том, какие поля входят в индекс и для какой таблицы. Название индекса, в отличие от названия полей является уникальным в пределах базы.
Активный – флаг активности индекса. При создании нового индекса всегда включен. При отключении данного флага оптимизатор запросов перестает учитывать индекс.
Уникальный – говорит о том, что поле (или совокупность полей) может иметь только уникальные значения в пределах таблицы.
Порядок – порядок построения индекса. Может быть по возрастанию и по убыванию.
Рис. 48 Диалоговое окно создания или изменения индекса Также мы видим два списка и кнопки навигации между ними. Левый список предоставляет все поля таблицы, за исключением тех, что пользователь уже выбрал в индекс, правый – выбранные для индекса поля. Порядок полей (если их выбрано больше одного) в индексе имеет значение. Сначала поиск будет идти по первому полю в индексе, затем по второму и т.д.
Хранимые процедуры Хранимая процедура – это объект базы данных, представляющий собой откомпилированную во внутреннее представление InterBase подпрограмму, написанную на специальном языке. Компилятор данного языка встроен в ядро сервера InterBase Хранимую процедуру можно вызывать из клиентских приложений, из триггеров и других хранимых процедур, использовать в запросах. Хранимая процедура выполняется внутри серверного процесса и может манипулировать данными в базе данных, а также возвращать результаты своего выполнения.
В хранимых процедурах можно использовать как обычные SQL-запросы (на выборку и изменение данных), так и средства организации условных ветвлений и циклов (IF, WHILE), а также генерировать исключения. Язык хранимых процедур позволяет реализовать сложные алгоритмы работы с данными, а, благодаря ориентированности на работу с реляционными данными, хранимые процедуры получаются значительно компактнее аналогичных процедур на традиционных языках. Кроме того в некоторых случаях хранимая процедура будет работать быстрее, чем, например, макрос.
Бизнес-классом, отвечающим за работу с хранимыми процедурами, является класс TgdcStoredProc.
Чтобы вызвать форму просмотра вам необходимо выбрать в исследователе пункт Сервис / Атрибуты / Процедуры. Вы можете добавлять / изменять / удалять любые пользовательские процедуры.
Диалог редактирования процедуры содержит две закладки:
Закладка Наименование содержит два поля для ввода:
Наименование процедуры – наименование процедуры на английском языке. Уникально в пределах базы. Не более 31 символа.
Описание процедуры – содержит краткую характеристику процедуры, что она делает, какие данные необходимо подать на вход, что она вернет. Необязательно для заполнения.
Закладка Текст процедуры содержит поле для ввода текста процедуры.
Триггеры Триггер в InterBase - это особый вид хранимой процедуры, которая выполняется автоматически при вставке, удалении или модификации записи таблицы или представления (view). Триггеры могут "срабатывать" непосредственно до или сразу же после указанного события. Т.е. вы можете создать шесть видов триггеров:
До вставки (Before Insert) После вставки (After Insert) До изменения (Before Update) После изменения (After Update) До удаления (Before Delete) После удаления (After Delete) Триггеры «до события» обычно используются для проверки введенных значений, указания значений по умолчанию и других операций, которые нужно выполнить пока данные в базе еще не успели измениться.
Триггеры «после события» используются для синхронизации данных. Например, после добавления записи в одну таблицу, вам необходимо добавлять запись в другую таблицу. Все действия, производимые в триггерах, выполняются на одной транзакции с самой операцией изменения данных.
Т.е., если у вас в триггере возникла ошибка, то все действия будут откачены.
В отличие от обычных хранимых процедур триггеры не могут иметь входных и выходных параметров, использоваться в запросах или непосредственно вызываться по имени.
Операции над триггерами можно производить из диалога редактирования таблицы. Существует также и форма просмотра триггеров, представляющая собой форму с master-detail связью, где мастер-объект – это таблица, а детальный объект – это триггер. Изначально это форма не доступна из исследователя. Однако вы сами можете добавить эту ветку при желании. Для этого необходимо добавить новый пункт исследователя, выбрать переключатель «Бизнес-объект», в выпадающем списке выбрать класс TgdcTrigger (бизнес-класс для работы с триггерами).
При открытии формы просмотра триггеров вам будет задан вопрос, синхронизировать ли триггеры с базой данных. Все дело в том, что в отличие от остальных объектов базы данных, отследить изменение триггеров практически невозможно. Сам по себе процесс синхронизации триггеров не очень быстрый, поэтому производить его каждый раз при загрузке системы нецелесообразно.
Диалог редактирования триггера (смотрите рисунок 8.7) содержит следующие поля для заполнения:
Наименование – наименование триггера на английском языке. Уникально в пределах базы.
Хотя, это и не обязательно, рекомендуется чтобы наименования триггеров соответствовали следующему шаблону: PREFIX_TYPE_TABLE_SUFFIX. Где, PREFIX — префикс подсистемы таблицы, для которой определен настоящий TYPE — тип триггера. Двухбуквенная аббревиатура.
TABLE — имя таблицы (без префикса) для которой определен триггер;
SUFFIX — суфикс, делающий имя тригера уникальным. Суфикс необходим, если для одной и той же таблицы на одну и ту же операцию создано более одного триггера. В качестве суффикса может использоваться номер позиции триггера.
Позиция – позиция триггера. Вы можете создать несколько триггеров на одно событие. Позиция указывает порядок их выполнения: первым выполнится триггер с нулевой позицией, вторым – с первой позицией и т.д. При совпадении позиций Interbase сам будет решать какой триггер выполнить первым.
Тип – тип триггера. Указывает для какого события он вызывается.
Активный – говорит о том, что триггер включен. Если этот флаг снять, триггер не будет вызываться при возникновении события.
Поле для ввода тела триггера – содержит тело триггера без шапки.
Рис. 49 Диалоговое окно просмотра и изменения триггера Представления (проекции) Представление (VIEW) - это виртуальная таблица, созданная на основе запроса к обычным таблицам.
Представление реализовано как запрос, хранящийся на сервере и выполняющийся всякий раз, когда происходит обращение к представлению. В некоторой вы также можете встретить также термин «Проекция».
Для чего нужны представления? Например, один и тот же запрос вы используете в различных местах.
Этот запрос может быть достаточно массивным, содержать много связанных таблиц. Представление предлагает «зашить» (спрятать) ваш запрос. Теперь, если вам нужно обратиться к данным, то достаточно выполнить коротенький запрос. Например, представление GD_V_COMPANY возвращает всю необходимую информацию для работы с организациями. При этом «лишние» (служебные) поля не отображаются. Сам по себе запрос выглядит следующим образом:
CREATE VIEW GD_V_COMPANY
(ID,COMPNAME, COMPFULLNAME, COMPANYTYPE, COMPLB, COMPRB, AFULL,
ACHAG, AVIEW, ADDRESS, CITY, COUNTRY, PHONE, FAX, ACCOUNT,BANKCODE, BANKMFO, BANKNAME, BANKADDRESS, BANKCITY,
BANKCOUNTRY, TAXID, OKPO, LICENCE, OKNH, SOATO, SOOU)SELECT
C.ID, C.NAME AS COMPNAME, COMP.FULLNAME AS COMPFULLNAME,
COMP.COMPANYTYPE, C.LB AS COMPLB, C.RB AS COMPRB,
C.AFULL, C.ACHAG, C.AVIEW, C.ADDRESS, C.CITY, C.COUNTRY, C.PHONE, C.FAX, AC.ACCOUNT, BANK.BANKCODE, BANK.BANKMFO,BANKC.NAME AS BANKNAME, BANKC.ADDRESS AS BANKADDRESS,
BANKC.CITY AS BANKCITY, BANKC.COUNTRY AS BANKCOUNTRY,
CC.TAXID, CC.OKPO, CC.LICENCE, CC.OKNH, CC.SOATO, CC.SOOU FROM GD_CONTACT CJOIN GD_COMPANY COMP ON COMP.CONTACTKEY = C.ID
LEFT JOIN GD_COMPANYACCOUNT AC
ON COMP.COMPANYACCOUNTKEY = AC.ID
LEFT JOIN GD_BANK BANK
ON AC.BANKKEY = BANK.BANKKEY
LEFT JOIN GD_COMPANYCODE CC
ON COMP.CONTACTKEY = CC.COMPANYKEY
LEFT JOIN GD_CONTACT BANKC
ON BANK.BANKKEY = BANKC.ID Согласитесь, что писать подобный запрос каждый раз, когда вам понадобятся данные по организациям в высшей степени утомительно. Однако, создав представление на основе этого запроса, вы сможете ограничиться следующим:SELECT * FROM gd_v_company Конечно, имеются и ограничения. В системе Гедымин вы не можете изменять данные непосредственно через представление.
Бизнес-классом для работы с представлениям является класс TgdcView, а для работы с полями представления TgdcViewField. Как вы понимаете, добавить поле в представление (или удалить его), можно только изменив запрос, на основании которого создано представление. Чтобы вызвать форму просмотра вам необходимо выбрать в исследователе пункт Сервис / Атрибуты / Представления. Вы можете добавлять / изменять / удалять любые пользовательские представления.
Диалог редактирования представления содержит четыре закладки:
Представление Текст представления Закладка Представление содержит следующие поля для заполнения:
Название представления(на английском языке) – собственно название представления. До символа. Внимание: название представлений и название таблиц должны быть уникальны в пределах базы, т.е. они не могут пересекаться.
Локализованное название представления – название на национальном языке.
Краткое название представления – аналогично локализованному, только в краткой форме.
Описание представления – характеристика представления, какие данные оно отображает.
Ветка для команды вызова в Исследователе – содержит ссылку на ветку исследователя, в которой будет содержаться ветка для вызова формы просмотра созданной таблицы. Т.е. мы указываем существующую ветку-родителя, а платформа сама создает в ней ветку для просмотра таблицы. Если этот параметр не указывать, то никакой ветки в исследователе создано не будет.
Поле для отображения(на английском) – аналогично параметру на диалоге редактирования Поля для расширенного отображения (на английском через запятую) – аналогично параметру на диалоге редактирования таблиц.
Соответствующий бизнес-класс – параметр заполняется системой Гедымин. Является информационным. Указывает пользователю, какой бизнес-класс представляет проекция.
Соответствующий подтип – работает в паре с предыдущим параметром. Указывает пользователю, какой подтип бизнес-класса представляет таблица. Для стандартных таблиц (без префикса USR$) будет всегда пустым.
Закладка Текст представления содержит поле для ввода запроса, на основании которого будет создано представление, и кнопку «Создать», по нажатию которой оно будет создано (или пересоздано – в режиме редактирования).
Закладка Поля появляется после создания представления. На ней вы можете просмотреть поля представления, а также отредактировать их визуальные характеристики.
Закладка Триггеры позволяет добавить триггеры, появляется после создания представления. Однако механизм изменения данных через представление в первой версии Гедымина еще не доработан. Поэтому особой пользы от этой закладки пока нет.
При создании представления через диалог редактирования будьте внимательны: для нормальной работы все as-наименования полей необходимо задать непосредственно в самом запросе. Вы можете даже не писать шапку с перечислением полей, платформа создаст ее сама. Т.е., возвращаясь к примеру GD_V_COMPANY. Для создания подобного представления вам было бы достаточно в поле для ввода запроса написать:
SELECT
C.ID, C.NAME AS COMPNAME, COMP.FULLNAME AS COMPFULLNAME,
COMP.COMPANYTYPE, C.LB AS COMPLB, C.RB AS COMPRB,
C.AFULL, C.ACHAG, C.AVIEW, C.ADDRESS, C.CITY, C.COUNTRY, C.PHONE, C.FAX, AC.ACCOUNT, BANK.BANKCODE, BANK.BANKMFO,BANKC.NAME AS BANKNAME, BANKC.ADDRESS AS BANKADDRESS,
BANKC.CITY AS BANKCITY, BANKC.COUNTRY AS BANKCOUNTRY,
CC.TAXID, CC.OKPO, CC.LICENCE, CC.OKNH, CC.SOATO, CC.SOOU FROM GD_CONTACT CJOIN GD_COMPANY COMP ON COMP.CONTACTKEY = C.ID
LEFT JOIN GD_COMPANYACCOUNT AC
ON COMP.COMPANYACCOUNTKEY = AC.ID
LEFT JOIN GD_BANK BANK
ON AC.BANKKEY = BANK.BANKKEY
LEFT JOIN GD_COMPANYCODE CC
ON COMP.CONTACTKEY = CC.COMPANYKEY
LEFT JOIN GD_CONTACT BANKC
ON BANK.BANKKEY = BANKC.ID Если же вы зададите в шапке представления другие наименования для полей, то при переносе представления на другую базу вы получите неприятности.Создание представления требует переподключения в базе данных. О переподключении к БД читайте далее.
Исключения Одной из рассматриваемых особенностей языка хранимых процедур и триггеров InterBase является возможность использовать «исключения». Исключения InterBase во многом похожи на исключения других языков высокого уровня, однако имеют свои особенности. Фактически исключение InterBase – это сообщение об ошибке, которое имеет собственное, задаваемое программистом имя и текст сообщения об ошибке на английском языке. Гедымин предоставляет пользователю возможность локализовать сообщение исключения.
Бизнес-классом, отвечающим за работу с исключениями интербейза, является TgdcException. Открыть форму просмотра исключений можно из исследователя Сервис / Атрибуты / Исключения. Диалог редактирования вызывается стандартно и выглядит как на рисунке 8.8. Диалог содержит следующие поля для заполнения:
Наименование – наименование исключения на английском языке, не более 31 символа.
Уникально в пределах базы.
Сообщение на английском – сообщение исключения на английском языке.
Локализованное сообщение – перевод сообщения с английского на национальный язык.
Рисунок 0. Вы можете создавать / изменять / удалять пользовательские исключения и модифицировать локализованное сообщение стандартных исключений.
Чтобы вызвать исключение из тела процедуры или триггера, необходимо написать следующую команду:
EXCEPTION
Возникновение исключения откатывает целиком всю операцию.Переподключение к базе данных. Окно состояния SQL Некоторые операции по изменению структуры базы данных достаточно трудоемки и не могут выполняться на одной транзакции. Более того, часть подобных операций требует переподключения к базе данных. Например, создание внешних ключей требует монопольного подключения к базе данных.
Когда вы создаете или изменяете объекты БД, используя средства Гедымина, то мастера сами выполняют пачку запросов. Те запросы, которые требуют переподключения, записываются в специальную таблицу AT_TRANSACTION (структура таблицы будет рассмотрена ниже). При следующем подключении к базе пользователю-администратору будет предложено в монопольном режиме (т.е. отключив всех остальных пользователей) выполнить данные запросы. В подобном режиме платформа сама определяет необходимость переподключения к базе для успешного выполнения всех операций. Те операции, которые не могут быть выполнены, удаляются из списка.
Кроме того, вы наверное обратили внимание, что при любом изменении структуры БД, на экране появляется окно Выполнение SQL команд (смотрите рисунок 8.9). Данное окно отображает последовательность выполняемых команд, состояние системы (имеется ввиду требуется ли переподключение к БД), возникшие ошибки. При этом служебная информация в обычном режиме выводится синим цветом, в режиме переподключения –зеленым; выполняемые команды – черным цветом, ошибки – красным цветом. Кроме того имеется еще строка состояния внизу окна, в которой отображается возникли ли ошибки в процессе выполнения и требуется ли переподключение к базе.
Максимально окно может хранить до 64 Кб текста. При достижении предела окно очищается. Однако, если вас интересует полностью весь лог выполнения сложной операции, вы можете нажать кнопку Сохранить вверху окна и сохранить его в текстовый файл.
Рисунок 0. Если вас не интересует статистика выполнения команд, вы можете отключить ее, сняв флаг в Сервис / Опции / Выводить лог при загрузке / сохранении в поток.
Теперь рассмотрим подробнее структуру таблицы AT_TRANSACTION, в которую помещаются отложенные команды.
NUMORDER DSMALLINT x Порядковый номер команды внутри одной транзакции.
Таблица 0. В заключение к выше сказанному можем повториться: все операции переподключения требуют монопольного доступа к БД. Если во время выполнения подобной операции кто-либо подключится к базе, то администратору будет выдано окно со списком подключившихся пользователей. Продолжить выполнение отложенных команд можно будет только после отключения лишних пользователей от базы.
Хитрый NULL Данная глава относится не столько к базе данных, сколько к SQL вообще. Однако с NULL значениями связано столько ошибок, что мы считаем своим долгом заострить на них внимание.
Итак, что такое NULL? NULL – это ПУСТО. В принципе, это означает, что поле не содержит никакого значения. NULL может присутствовать как в текстовых, так и в числовых полях, или, проще говоря, поле любого типа может содержать NULL, если это не оговорено специально. Под фразой «оговорено специально» мы понимаем ограничения, налагаемые на содержимое полей.
Чем же так коварен NULL? Поля, содержащие NULL-значения не могут напрямую участвовать в операциях сравнения. Операции сравнения (>, >» на нижней панели формы. Чтобы удалить лишнее условие, нужно нажать на кнопку «Удалить» на нижней панели формы или на крестик в верхнем правом углу условия.
Рисунок 0. Рисунок 0. Теперь рассмотрим подробнее содержимое области «Наименование поля». Данное поле может принимать следующие значения:
• Формула – предлагает настройщику добавить условия в запрос вручную. При этом поле «Условия фильтра» предлагает выбрать одну из двух операций:
• ввести условия – настройщику выводится окно с областью для добавления условий в • создать запрос – настройщику выводится окно с областью для изменения существующего запроса. Изменяя запрос бизнес-объекта, помните: не следует изменять • Выбранное поле – т.е. данная область содержит список таблиц, использующихся в базовом запросе бизнес-объекта, для каждой таблицы список полей и список ссылок на эту таблицу.
В зависимости от типа выбранного поля область «Условия фильтра» заполняется определенными операциями.
Выбранное поле может быть одним из следующих типов:
• Ссылка на другую таблицу - поле текущей таблицы списка, являющееся ссылкой на • Поле данных - поле текущей таблицы списка, хранящее числовые, текстовые, временные (дата, время) или BLOB данные.
• Множество - поле внешней таблицы-множества, которое ссылается на ключевое поле текущей таблицы. При этом в расшифровке указывается название таблицы-множества и название поля, являющегося внешней ссылкой на текущую таблицу.
• Внешняя ссылка - поле внешней таблицы, которое ссылается на ключевое поле текущей таблицы. При этом в расшифровке указывается название таблицы и название поля, являющегося внешней ссылкой на текущую таблицу.
Область «Условия фильтра» может принимать следующие значения:
• больше – используется для полей числовых и временных типов. Требует указания фиксированного порога. Если значение указанного поля будет больше данного порога, то • больше или равно – используется для полей числовых и временных типов. Требует указания фиксированного порога. Если значение указанного поля будет больше или равно данного порога, то условие верно.
• включает – используется для полей множеств или внешних ссылок. Требует указания фиксированного набора значений. Если данные значения содержатся в таблице-множестве или внешней таблице, то они будут отображены.
• вне вкл. границы – используется для полей числовых и временных типов. Требует указания фиксированных границ. Если значение указанного поля вне или равно данным границам, то • вне искл. границы – используется для полей числовых и временных типов. Требует указания фиксированных границ. Если значение указанного поля вне данных границ, то • доп. фильтрация – используется только для полей-множеств. Позволяет открыть диалог для фильтрации по полям таблицы-множества.
• за выбранный день – используется для полей временных типов. Требует указания фиксированной даты. Если значение указанного поля будет равно этой дате, то условие • за сегодня – используется для полей временных типов. Если значение указанного поля будет равно текущей дате, то условие верно.
• заканчивается на – используется для текстовых полей. Требует указания фиксированного текста. Если значение указанного поля будет заканчиваться на данный текст, то условие верно. Поиск текста не зависит от регистра.
• запрос параметра – используется для всех типов полей, за исключением полей типа BLOB.
Выводит окно с запросом параметра, соответствующего типу поля. При применении фильтра пользователь должен указать значение параметра. Последний указанный параметр сохраняется в настройках пользователя.
• между вкл. границы – используется для полей числовых и временных типов. Требует указания фиксированных границ. Если значение указанного поля внутри или равно данным • между искл. границы – используется для полей числовых и временных типов. Требует указания фиксированных границ. Если значение указанного поля внутри данных границ, то • меньше – используется для полей числовых и временных типов. Требует указания фиксированного порога. Если значение указанного поля будет меньше данного порога, то • меньше или равно – используется для полей числовых и временных типов. Требует указания фиксированного порога. Если значение указанного поля будет меньше или равно данного порога, то условие верно.
• начинается с – используется для текстовых полей. Требует указания фиксированного текста. Если значение указанного поля начинается на данный текст, то условие верно. Поиск • не включает – используется для полей-ссылок, множеств или внешних ссылок. Требует указания фиксированного набора значений. Для полей ссылок используется условие «не в списке». Для полей множеств или внешних ссылок данные выводятся в соответствии с существованием на них ссылок из внешних таблиц или таблиц-множеств, исключая • не включает ветвь – используется для полей-ссылок или множеств, если текущая таблица является интервальным деревом. Требует указания фиксированного набора значений.
Исключает из выборки не просто значения из набора, но и целиком всю ветку, которая • не равно – используется для полей текстовых, числовых и временных типов. Требует указания фиксированного значения. Если текущее поле не равно указанному значению, то условие верно. Для текстовых полей сравнение идет без учета регистра. (!!!! проверить про • не содержит – используется для текстовых полей. Требует указания фиксированного текста.
Если значение указанного поля не содержит данный текст, то условие верно. Поиск текста • не существует – используется для полей всех типов. Проверяет поле на NULL. Если поле содержит NULL, то условие верно.
• один из – используется для полей-ссылок, множеств, внешних ссылок. Требует указания фиксированного набора значений. Если указанное поле входит в данных набор, то условие верно. При работе с полями-множествами и внешними ссылками данные значения должны также присутствовать в этих таблицах.
• одна ветвь из – используется для полей-ссылок и множеств, если текущая таблица – интервальное дерево. Требует указания фиксированного набора значений. Если указанное поле входит в данных набор или является вложенным значением для значения из набора, то условие верно. При работе с полями-множествами данные значения должны также присутствовать в таблице-множестве.
• последние дней – используется только для временных типов. Требует указания фиксированного значения количества дней. Записи будут отфильтрованы по указанному полю, содержащему значения от текущей даты минус фиксированное количество дней.
• равно – используется для полей текстовых, числовых и временных типов. Требует указания фиксированного значения. Если текущее поле равно указанному значению, то условие верно. Для текстовых полей сравнение идет без учета регистра. (!!!! проверить про регистр) • скрипт – используется для всех типов полей. Позволяет указать условие для выбранного • содержит – используется для текстовых полей. Требует указания фиксированного текста.
Если значение указанного поля содержит данный текст, то условие верно. Поиск текста не • существует – используется для полей всех типов. Проверяет поле на NULL. Если поле содержит какое-либо значение, то условие верно.
• фильтрация – используется для полей-ссылок, множеств и внешних ссылок. Позволяет открыть диалог для фильтрации по полям таблиц, на которые идет ссылка.
Закладка Сортировка предоставляет возможность добавить в запрос сортировку по одному или нескольким полям (сравните с сортировкой данным в гриде). Чтобы добавить следующее условие сортировки, необходимо нажать на кнопку «А также >>» на нижней панели формы. Чтобы удалить лишнее условие, нужно нажать на кнопку «Удалить» на нижней панели формы или на крестик в верхнем правом углу условия. Внизу закладки находится признак «Разрешать сортировку только по полям, для которых создан индекс в базе». При установке данного признака, в списке полей будут отображаться только индексированные поля. Вы можете упорядочить записи по возрастанию или по убыванию. При указании признака только индексированных полей порядок сортировки берется из индекса.
Закладка SQL содержит две кнопки: текст исходного SQL-запроса (т.е. запроса бизнес-объекта без применения фильтрации), текст SQL-запроса с условиями фильтрации (т.е. запроса с применением текущих условий). По нажатию одной из этих кнопок перед вами появляется SQL-редактор, в котором вы можете отладить запрос. Внимание! Изменения в SQL-редакторе не сохраняются. Он предназначен только для тестирования запроса.
Хранение фильтров в базе В данной подглаве рассматривается структура таблиц, предназначенных для хранения фильтров. Все таблицы для работы с фильтрами начинаются с префикса FLT_ (смотрите таблицу 9.1).
FLT_COMPONENTFILTER Каждый фильтр как компонент имеет уникальное название, состоящее из FLT_LASTFILTER Хранит ссылку на последний использовавшийся фильтр для указанного FLT_PROCEDUREFILTER Не используется.
FLT_SAVEDFILTER Хранит отдельные фильтры, созданные пользователем, их описание, права Таблица 0. Теперь рассмотрим структуру каждой таблицы по отдельности.
Таблица FLT_COMPONENTFILTER.
Таблица 0. Таблица FLT_LASTFILTER.
Таблица 0. Таблица FLT_SAVEDFILTER.
Таблица 0. Использование фильтрации для TIBDataset и TIBQuery Итак, для бизнес-объекта компонент фильтрации создается автоматически. Что же делать, если вы используете обычный TIBDataSet или TIBQuery, и при этом хотите использовать фильтрацию? Для таких случаев создан компонент TQueryFilterGDC. Его достаточно положить на форму и в свойстве IBDataSet указать, какой набор данных вы желаете фильтровать. Затем вам нужно создать кнопку, которой будет вызываться меню фильтра и на OnClick прописать вызов.
sub usrg_ButtonFilterOnClick(ByVal Sender) ‘находим компонент фильтрации на форме Sender.OwnerForm.GetComponent("usrg_QueryFilterGDC") call FilterComponent.PopupMenu(-1, -1) Пример использования фильтрации для TIBDataSet можно посмотреть в Разноске по счетам (настройка «Бухгалтерия»).
Отчеты Схематически, компоненты процесса построения отчета в системе Гедымин можно изобразить следующим образом:
принтер Рис. 50 Компоненты процесса создания отчета.
Вкратце, схема создания отчета такова: функция построения отчета извлекает данные из базы данных или внешних источников и помещает их в специальную внутреннюю структуру. На вход функции могут быть переданы параметры, которые могут быть запрошены у пользователя или сформированы автоматически функцией параметров. Далее, Гедымин подставляет данные из внутренней структуры в шаблон, в результате чего получается готовый, сформированные отчет. Этот отчет может быть отображен на экране, отпечатан на принтере, сохранен на диске или экспортирован в другие программы (например, в Microsoft Excel). Отчет, отображаемый на экране, можно сделать интерактивным. Для этого создается функция обработки событий, которая вызывается в ответ на щелчок мышью по той или иной части отчета.
Рассмотрим каждый компонент, участвующий в описанном процессе, более подробно:
Функция построения отчета Функция построения отчета, она же основная функция отчета, возвращает список наборов данных (dataset), которые будут доступны в шаблоне отчета. Работа со списком происходит через глобальный объект BaseQueryList. Как правило, в первых строках функции объект BaseQueryList очищается вызовом метода Clear. Далее, с помощью метода BaseQueryList.Add создаются и добавляются в список новые наборы данных, при этом задается имя набора и его тип. Поддерживаются два типа: набор данных, являющийся результатом выполнения SQL запроса к базе данных и таблица в оперативной памяти компьютера. После создания набора данных первого типа, необходимо задать текст запроса, присвоить параметры (если они есть) и выполнить запрос. Во втором случае, необходимо создать поля в таблице и заполнить ее вручную, добавляя записи по-одной. Ниже приводится пример основной функции, в котором создаются по одному набору данных каждого типа:
function rp_MyReport ‘ объект BaseQueryList глобальный, поэтому ‘ его необходимо очистить перед использованием BaseQueryList.Clear ‘ создадим набор данных на основании SQL запроса ‘ который извлечет из базы данных список пользователей системы ‘ назовем его SQLQuery (под этим именем набор данных ‘ будет виден в списке наборов в дизайнере шаблона отчета set Q = BaseQueryList.Query(BaseQueryList.Add(“SQLQuery”, 0)) Q.SQL = “SELECT * FROM gd_user” ‘ укажем, что набор следует показывать с списке ‘ наборов данных в дизайнере Q.IsResult = ‘ выполняем запрос Q.Open ‘ создадим набор данных типа таблица с двумя полями:
‘ целочисленным полем “ID” и строковым полем “Name” ‘ оба поля обязательны для заполнения ‘ назовем набор данных “MemTable” dim MT set MT = BaseQueryList.Query(BaseQueryList.Add(“MemTable”, 1)) MT.AddField “ID”, “ftInteger”, 0, True MT.AddField “Name”, “ftString”, 60, True MT.Open ‘ добавим одну запись MT.Append MT.FieldByName(“ID”).AsInteger = MT.FieldByName(“Name”).AsString = “Name” MT.Post MT.IsResult = ‘ перед выходом из функции не забудем вернуть ‘ сформированный список наборов данных set rp_MyReport = BaseQueryList end function Данные Большинство отчетов строится на основании информации из базы данных. Для ее извлечения применяются SQL запросы. Кроме этого, возможно использование любых других источников данных:
массивов, StringGrid-ов, данных из файлов и т.п. Подключение к внешним источникам данных может осуществляться через объекты ADO, при наличии соответствующих драйверов доступа ODBC или провайдеров OLE DB.
Параметры Функция построения отчета может иметь входные параметры. Например, параметрами могут быть начальная и конечная даты периода, за который берутся данные для построения отчета и т.п. Если просто задать параметры в заголовке функции, Гедымин автоматически будет запрашивать их у пользователя при выполнении данного отчета. Каждый параметр можно настроить: указать его тип, снабдить, понятным пользователю названием. Рассмотрим следующий пример: пусть функция построения отчета определена как:
function rp_CustomerList(DateBegin, DateEnd) Выполнена настройка параметров:
При запуске отчета на выполнение на экран будет выведено окно запроса параметров:
Шаблон Пример простого отчета Рассмотрим пример создания простого отчета — списка организаций клиентов, содержащихся в базе данных, с выводом наименования организации, ее адреса и контактного телефона.
В Гедымине существует три типа отчетов: отчеты, привязанные к конкретной форме (будут отображаться в меню отчетов этой формы), отчеты, привязанные к определенному типу бизнес объекта (будут выводиться в меню отчетов любой формы, на которой лежит объект такого типа) и, наконец, отчеты ни к чему не привязанные. Такие отчеты доступны через форму Отчеты, вызываемую из Исследователя. Стоит заметить, что для любого отчета можно просто добавить команду вызова в Исследователь. В этом случае доступ к отчету можно будет получить непосредственно, без открытия промежуточных форм.
В нашем случае мы создадим отчет, привязанный к форме справочника клиентов. Последовательность действий следующая:
1. Откроем справочник клиентов. Для этого зайдем в Исследователь, найдем в нем раздел Справочники и дважды щелкнем по ветке Клиенты в этом разделе;
2. На панели инструментов отыщем изображение принтера (команда «Печать») и щелкнем по 3. На экране откроется всплывающее меню. Выберем в нем команду «Редактор скрипт-объектов»;
4. На экране откроется окно редактора скрипт-объектов;
5. В Проводнике редактора скрипт-объектов необходимо установить курсор на папку «Отчеты Если окно проводника закрыто, его необходимо открыть, вызвав соответствующую команду в меню «Окна» редактора скрипт-объектов.
6. По правой кнопке мыши вызовем контекстно-зависимое меню и выберем команду «Добавить 7. На рабочей области редактора скрипт-объектов откроется набор закладок, предназначенных для работы с основными компонентами отчета: функцией построения (закладка «Основная функция»), функцией параметров, функцией событий и шаблоном отчета, а также для изменения свойств отчета (закладка «Свойства»).
Свойства отчета Рис. 51 Свойства отчета.
На закладке «Свойства» располагаются следующие поля:
• Наименование отчета. Наименование отчета так, как оно будет отображаться в меню отчетов • Комментарий. Произвольный текстовый комментарий;
• Частота обновления отчета. В настоящий момент данное поле не используется. Может быть заполнено произвольным образом;
• Отображать в папке. Из выпадающего списка можно выбрать папку Исследователя, куда будет помещен отчет. Если поле заполнить, то отчет можно будет вызвать как из меню «Печать» на форме, так и путем вызова соответствующей команды в Исследователе системы. Команда будет иметь такое же наименование, как и наименование отчета и располагаться в заданной папке.
Если в последствии потребуется удалить команду из Исследователя, то для этого достаточно очистить поле и пересохранить отчет;
• Отображать в меню отчетов формы. Если галочка снята, то наименование отчета не будет отображаться в меню отчетов формы;
• Отображать отчет перед печатью. Если галочка снята, то при выполнении отчета он будет сразу же выводиться на печать без предварительного просмотра на экране.
Кроме этого, на вкладке свойства можно настроить права доступа к данному отчету. Соответствующая кнопка называется «Дополнительные свойства» и располагается на панели инструментов, непосредственно над полем «Наименование отчета».
Основная функция На вкладке «Основная функция» осуществляется редактирование функции построения отчета.
Рис. 52 Вкладка "Основная функция" Разграничение прав доступа Только пользователя, являющиеся членами групп «Администраторы», «Опытные пользователи» или «Операторы печати» имеют право редактировать построенный отчет в режиме просмотра, перед его отправкой на принтер.
FastReport Функции • SumStr(Number: Double; Precision: Integer) Возвращает число Number прописью, количество знаков после запятой ограничивается параметром Precision (не более 4).
Пример: SumStr(0.005, 3) — “Ноль целых пять тысячных”.
xFastReport Описание формата файла-формы Файл-форма представляет собой набор блоков. Каждый блок содержит формат вывода той или иной части отчета.
Расположение блоков Для обозначения начала блока используется строка, состоящая из символа % (в первой позиции) и следующего за ним названия блока (не отделенного пробелами). Все содержимое файла до начала первого блока игнорируется. Весь текст, следующей за именем блока (в той же строке) тоже игнорируется.
Файл - форма должен содержать следующие блоки (строго в указанном порядке):
%Report - текст, печатаемый в начале отчета %Page - текст, печатаемый в начале каждой страницы %TableHeader - заголовок таблицы (печатается на каждой странице) %TableRecord - формат вывода одной записи (каждая запись будет напечатана на одной %TableSeparator - текст, отделяющий одну запись от другой %TableFooter - текст, печатаемый внизу таблицы на каждой странице (кроме последней) %TableEnd - текст, печатаемый в конце таблицы (на последней странице) %Page - текст, печатаемый в конце каждой страницы %Report - текст, печатаемый в конце отчета Кроме указанных блоков файл-форма может содержать следующие блоки (в произвольном месте файла):