Выбрать главу

Если вы хотите применять строковые параметры, то вы должны использовать тип CSTRING В скобках необходимо указать максимальную длину строки. Если строка является результатом функции, она всегда передается по ссылке, а не по значению.

Параметр FREE_IT указывает InterBase, что после выполнения функции необходимо автоматически освободить память, выделенную для параметров. Очевидно, данная опция нужна только в том случае, если наша библиотека сама мм делила память под какие-либо параметры функции.

В параметре entryname необходимо указывать название функции в DLL, ко торую мы собственно и хотим декларировать как пользовательскую функцию.

В параметре modulename необходимо указать название файла DLL, в котором находится декларируемая функция пользователя.

Стоит заметить, что параметры entryname и modulename регистрочувствительные.

Таким образом, чтобы добавить нашу функцию в базу данных, нам необходимо выполнить следующую команду:

DECLARE EXTERNAL FUNCTION USTRUPPERCASE

cstring(254)

RETURNS cstnng(254) FREE_IT

ENTRY_POINT 'StrUpperCase' MODULE_NAME 'TestUDF.dll'

После этого мы сможем использовать новую функцию USTRUPPERCASE в любом SQL-запросе. Например, мы можем проверить, как работает функция на следующем запросе:

SELECT USTRUPPERCASE(DEPARTMENT) FROM DEPARTMENT

Запрос вернет названия отделов из таблицы DEPARTMENT:

Рис 1.5. Результат использования UDF USTRUPPERCASE

Заключение

Мы рассмотрели на примере, как можно расширять набор доступных SQL-функций при помощи механизма User Defined Functions. Имея этот простой, но очень мощный механизм, вы сможете сделать обработку бизнес-правил в ваших базах данных гораздо более эффективно и удобно. В сущности, механизм пользовательских функций InterBase имеет только одно серьезное ограничение - он не позволяет обрабатывать NULL-параметры. В остальном функциональность пользовательских "расширений" SQL зависит только от ваших потребностей.

Широкий выбор UDF-библиотек, а также более подробную информацию об их использовании и разработке всегда можно найти на сайтах www.InterBaseworld.com и www.ibase.ru.

Русификация InterBase

Borland InterBase 6.x и его клоны Firebird и Yaffil - продукты, ориентированные на международного потребителя и позволяющие работать со множеством разных языков, в том числе и русским. Однако по умолчанию InterBase будет ориентироваться на работу с английским языком, поэтому для того, чтобы хранить в базе данных кириллицу и иметь возможность извлекать ее в читабельном виде, необходимо произвести ряд действий по "русификации" базы данных и включению поддержки кириллицы в клиентских приложениях.

Русификация базы данных InterBase

Наборы символов

Чтобы указать InterBase, как интерпретировать и хранить помещаемую в базу данных символьную информацию, необходимо указать набор символов (.character set), который будет использоваться для представления этих символов в нужном виде (см. выше главу "Типы данных" для информации о хранении символьных данных). Чтобы пользоваться набором символов, необходимо указать его как атрибут объектов в базе данных, а также указать его для использования в клиентском приложении.

Если вы уверены в том, каким набором символов будете пользоваться в вашей базе данных, то можете установить единый набор символов по умолчанию для всей базы данных. Для этого в команде создания базы данных следует указать набор символов по умолчанию с помощью опции DEFAULT CHARACTER SET. Для того чтобы работать с русскими буквами, следует указывать набор символов WIN1251. Можно также использовать набор UNICODE_FSS, который поддерживает любые символы UNICODE в представлении UTF-8. Однако большинство производителей библиотек доступа не полностью поддерживают этот набор символов, поэтому лучше использовать проверенный WIN1251.

Чтобы указать набор символов по умолчанию для всех объектов базы данных, надо применить команду наподобие этой:

CREATE DATABASE 'C:\Database\rusbase.gdb' USER 'SYSDBA' PASWORD

'masterkey' DEFAULT CHARACTER SET WIN1251;

Указание набора символов по умолчанию не означает, что все таблицы и поля в базе данных должны иметь тот же самый тип. Они будут использовать этот набор символов, если явно не указать какой-нибудь другой. Мы всегда можем переопределить набор символов. Например, мы можем создать таблицу, в которой 3 поля имеют разные наборы символов:

CREATE TABLE langTable(

NAME_RUS VARCHAR(255) CHARACTER SET WIN1251,

NAME_ENG VARCHAR(255) CHARACTER SET WIN1250,

NAME_UNI VARCHAR(255) CHARACTER SET UNICODE_FSS);

Однако, создав такую таблицу, не думайте, что вы сможете с помощью одного SQL-запроса заносить данные на разных языках в эту таблицу. Дело в том,

что при подключении к базе данных приложение также должно указывать набор символов (см. ниже), при помощи которого оно будет интерпретировать получаемые данные. Поэтому, чтобы записать в каждое поле символы из разных наборов данных, он должен трижды подключиться к базе данных с указанием разных наборов символов либо использовать набор UNICODE_FSS, если клиентская библиотека это позволяет.

Хранение символьных данных без использования наборов символов

Считать данные таблицы, в которой символьные поля имеют разные наборы символа с помощью одного SQL-запроса также не получится, если мы укажем один из трех наборов данных, то InterBase попытается привести все данные к этому набору, а это может у него не получиться - и тогда возникнет ошибка "Cannot transliterate characters between character sets".

Однако существует еще один, недокументированный способ хранить в базе данных символы из различных наборов. Этот способ заключается в том, чтобы вообще не указывать набор символов, тогда по умолчанию будет применять character set NONE, использование которого дает понять InterBase, что символьные данные должны храниться так, как они есть, без всяких интерпретаций. При этом всю ответственность за интерпретацию данных берет на себя разработчик клиентского приложения. Таким образом, отказавшись от использования наборов символов, мы получаем возможность читать и хранить любые символьные данные.

Казалось бы, надо всегда пользоваться CHARACTER SET NONE и избегать различных проблем, однако, отказываясь от наборов символов, мы отказываемся и от полезных свойств, которые они с собой несут. Прежде всего, использование CHARACTER SET, а, точнее, их COLLATION ORDERS (способов упорядочения) позволяет корректно сортировать русские символы и приводить их к верхнему регистру.

Дело в том, что по умолчанию русские буквы сортируются в двоичном порядке, т. е. в соответствии с порядком расположения кодов символов. При этом строчные буквы располагаются после прописных, а буква "Ы" вообще располагается отдельно. Чтобы заставить их сортироваться правильно, надо указать способ упорядочения, т. е. COLLATION ORDER.

Вносим ясность

У начинающих разработчиков часто возникает путаница в голове от многочисленных опций, определяющих поведение InterBase с русскими буквами. Вероятно, дочитав до этого места, вы уже достаточно запутались во множестве взаимнопересекающихся определений. Чтобы внести ясность в эти понятия, давайте еще раз их прокомментируем.

Основа всего - символьные типы InterBase, которые позволяют хранить в каждом поле до 32767 байт. Однако байты в общем случае не равнозначны символам, потому что в различных системах кодировки для представления одного символа могут использоваться 1, 2 или даже 3 байта. Таким образом, когда мы определяем поле типа CHAR или VARCHAR, то мы задаем количество символов, которые там могут поместиться, а количество байтов определяется умножением заданной длины на максимальный размер символа для данного набора символов Для набора символов WIN1251 любой символ занимает 1 байт, поэтому размер поля в байтах будет равен объявленной длине. А вот при использовании кодировки UNICODE_FSS максимальный размер символа составляет 3 байта; таким образом, реальная длина поля будет равна утроенному объявленному размеру. Вы не сможете создать поле с кодировкой UNICODE_FSS с длиной более чем 32767 div 3 = 10921 символ. В то же время реальный размер символа может быть меньше максимального, использовавшегося InterBase для расчета размера поля, т. е. вы сможете записать в такое поле больше символов, чем его объявленная длина!