Firebird РУКОВОДСТВО РАЗРАБОТЧИКА БАЗ ДАННЫХ - Хелен Борри
Шрифт:
Интервал:
Закладка:
MINUTE
SMALLINT
0-59
Допустимо
Не допустимо
Допустимо
SECOND
DECIMAL(6,4)
0-59.9999
Допустимо
Не допустимо
Допустимо
WEEKDAY
SMALLINT
0-6*
Допустимо
Допустимо
Не допустимо
YEARDAY
SMALLINT
1-366
Допустимо
Допустимо
Не допустимо
* 0 = воскресенье ... 6 = суббота.
Объединение EXTRACT() с другими функциями
Далее следуют два примера использования функции EXTRACT() внутри CAST() для получения представлений даты, которые не могут быть получены использованием одной из функций.
Получение даты и времени без долей секундыХотя невозможно прямым преобразованием получить строку даты и времени без долей секунды, это может быть сделано при использовании выражения, включающего обе функции CAST() и EXTRACT().
Выделение строки времениЭта техника больше нужна в диалекте 1, чем в диалекте 3. Тем не менее она может быть экстраполирована на любой тип даты или времени диалекта 3, если вам нужно сохранять время дня в виде строки.
Функция EXTRACT() делает возможным выделение отдельных элементов типов даты и времени в значения SMALLINT. Следующий триггер выделяет элементы времени из столбца диалекта 1 DATE с именем CAPTURE_DATE и преобразует их в CHAR (13), имитируя стандартный в Firebird литерал времени 'HH:MM:ss.nnnn'.
SET TERM ^;
CREATE TRIGGER BI_ATABLE FOR ATABLE
ACTIVE BEFORE INSERT POSITION 1
AS
BEGIN
IF (NEW.CAPTURE_DATE IS NOT NULL) THEN
BEGIN
NEW. CAPTURE_TIME =
CAST(EXTRACT (HOUR FROM NEW.CAPTUEE_DATE) AS CHAR(2)) || ':' ||
CAST(EXTRACT (MINUTE FROM NEW.CAPTURE_DATE) ASCHAR(2)) || ':' ||
CAST(EXTRACT (SECOND FROM NEW.CAPTURE_DATE) AS CHAR(7));
END
END ^
SET TERM ; ^
Пример преобразования типа дата/времяСтрока CHAR (13), сохраняемая триггером в предыдущем примере, не имеет того "поведения," что тип TIME в диалекте 3. Тем не менее при простом преобразовании она может быть конвертирована напрямую в тип TIME диалекта 3 при последующем обновлении до диалекта 3.
Сначала мы добавляем новый временный столбец в таблицу для хранения конвертированной строки времени:
ALTER TABLE ATABLE
ADD TIME_CAPTURE TIME;
COMMIT;
Затем заполняем временный столбец строкой времени, выполняя преобразование в диалекте 1:
UPDATE ATABLE
SET TIME_CAPTURE = CAST (CAPTURE_TIME AS TIME)
WHERE CAPTURE_TIME IS NOT NULL;
COMMIT;
Следующая вещь, которую мы должны сделать, - это временно удалить в нашем триггере ссылку на строку времени диалекта 1. Это нужно, чтобы устранить проблемы зависимости при изменении старой строки времени.
SET TERM ^;
RECREATE TRIGGER BI_ATABLE FOR ATABLE
ACTIVE BEFORE INSERT POSITION 1
AS
BEGIN
/* ничего не выполняется */
END ^
SET TERM ;^
COMMIT;
Теперь мы можем удалить старый столбец CAPTURE_TIME:
ALTER TABLE ATABLE DROP CAPTURE_TIME;
COMMIT;
Создадим его опять, на этот раз как тип TIME:
ALTER TABLE ATABLE
ADD CAPTURE_TIME TIME;
COMMIT;
Перепишем данных из временного столбца в только что добавленный столбец
CAPTURE_TIME:
UPDATE ATABLE
SET CAPTURE_TIME = TIME_CAPTURE
WHERE TIME_CAPTURE IS NOT NULL;
COMMIT;
Удалим временный столбец:
ALTER TABLE ATABLE DROP TIME_CAPTURE;
COMMIT;
Под конец изменим триггер так, чтобы он теперь записывал значение CAPTURE_TIME как тип TIME:
SET TERM ^;
RECREATE TRIGGER BI_ATABLE FOR ATABLE
ACTIVE BEFORE INSERT POSITION 1
AS
BEGIN
IF (NEW.CAPTURE_DATE IS NOT NULL) THEN
BEGIN
NEW.CAPTURE_TIME = CAST (NEW.CAPTURE.DATE AS TIME);
END
END ^
SET TERM ;^
COMMIT;
Все эти шаги могут быть записаны в скрипте SQL. Подробности использования скриптов SQL см. в разд. "Скрипты схемы" главы 14.
Понимание функции EXTRACT()
Функция EXTRACT() вызывает исключение, если она получает пустой аргумент. Этот факт можно использовать в простых запросах для проверки условия NOT NULL или в выражениях подзапросов при декодировании полей типа дата/время. Тем не менее во внешних соединениях это не столь просто, потому что потоки внешнего соединения, которые не соответствуют условиям последнего, возвращают NULL в незаполненных полях.
Рекомендуется использовать подзапрос (см. главы 21 и 22), который ограничивает вызовы функции только при ненулевых значениях. В диалекте 3 есть другое решение: использовать выражение CASE (см. главу 21) для исключения вызова EXTRACT() при нулевых датах.
Пора дальшеСледующая глава охватывает большую тему использования символьных (строковых) типов данных в Firebird, включая важные вопросы определения и работы с интернациональными наборами символов и порядком сортировки для баз данных и столбцов.
ГЛАВА 11. Символьные типы данных.
Firebird поддерживает символьные (строковые) типы данных фиксированной и переменной длины. Они могут быть определены для локального использования в любом наборе символов, выбираемом из большого списка. Символьные типы фиксированной длины не могут превышать 32 767 байт абсолютной длины; для типов переменной длины этот предел уменьшается на два байта, которые при сохранении строки содержат счетчик символов.
Firebird хранит строки очень экономно, используя простой алгоритм сжатия данных, даже если это тип CHAR или NCHAR. В том случае, когда вы хотите объявить очень большой строковый столбец, помните, что существует множество причин не использовать длинные строки - ограничения клиентской памяти или размеров индекса, а для Firebird 1.0.x еще и декомпрессия строк фиксированной и переменной длины в объявленную длину до того, как они покинут сервер.
Основы использования строк
Атрибут символьных типов CHARACTER SET важен не только для совместимости с интерфейсом локализованных приложений, но также в некоторых случаях для определения размера столбца. Отдельные наборы символов используют несколько байтов для хранения одного символа- обычно два или три в Firebird. Когда используются такие наборы символов, максимальный размер уменьшается в два или три раза.
! ! !
ПРИМЕЧАНИЕ. Атрибут CHARACTER SET в объявлении является необязательным. Если никакой набор символов не определяется на уровне столбца, то атрибут CHARACTER SET устанавливается в значение набора символов по умолчанию для базы данных. Механизм определения набора символов для столбцов и переменных обсуждается более подробно позже в этой главе.
. ! .
Попытка помещения в строковый столбец Firebird строки с длиной, превышающей объявленную, вызывает ошибку переполнения.
Ограничитель строки
Ограничителем строк в Firebird является символ ASCII 39, или одиночная кавычка, или апостроф, например,
StringVar = 'This is a string.';
Двойные кавычки вовсе запрещены для ограничения строк. Вы должны помнить это, если соединяетесь с БД Firebird, используя код приложения, написанного для баз данных InterBase 5, где разрешалось использовать кавычки в качестве ограничителя строк. Строки должны быть исправлены также в исходном коде хранимых процедур и триггеров в базе данных InterBase 5, если вы планируете перекомпилировать их для Firebird.
Конкатенация
Firebird использует стандартный в SQL символ для конкатенации (соединения) строк: двойной символ ASCII с кодом 124, известный как двойная вертикальная черта (||). Он может быть использован для конкатенации строковых констант, строковых выражений и/или значений столбцов, например:
MyBiggerString = 'You are my sunshine, ' || FirstName || ' my only sunshine.';
Символьные элементы могут соединяться с числами и числовыми выражениями для получения алфавитно-цифровых строк. Например, для конкатенации символа '#' с целым:
NEW.TICKET_NOMBER = '#' || NEW.PK_INTEGER;
! ! !
ВНИМАНИЕ! He используйте выражения конкатенации, где один из элементов может иметь значение NULL. Результатом любой конкатенации, содержащей NULL, будет NULL.
. ! .
Управляющие символы
Как правило, Firebird не поддерживает использование управляющих символов для включения непечатаемых кодов или последовательностей в строковые поля. Единственным исключением является "дублирование" символа апострофа (ASCII 39) для включения его в качестве хранимого символа и исключения его интерпретации как терминального ограничителя строки:
. . .
SET HOSTELRY = 'О''Flaherty''s Pub'
. . .
В строках можно хранить непечатаемые символы. Может быть объявлена функция UDF Asciichar (ascii_значение) в библиотеке ib udf, чтобы дать возможность передавать в строки такие символы или их последовательности. Следующий оператор выводит множество текстовых полей - например, во внешний файл - с символами возврата каретки и перевода строки в последнем поле:
INSERT INTO EXTFILE(DATA1, DATA1, DATA3, CRLF)
VALUES ('String1', 'String2', 'String3', Ascii_Char(13) || Ascii_Char(10));
По поводу объявления Asciichar (..) и других функций в библиотеке ib udf смотрите в подкаталоге ../UDF в корневом каталоге инсталляции Firebird скрипт с именем ib udf.sql. Подробности о внешних функциях см. в приложении 1.
Ограничения символьных типов
Ограничения многобайтовых наборов символовВажно быть в курсе того, как многобайтовые наборы символов влияют на размеры текстовых элементов, особенно имеющих переменный размер. Например, в наборе символов UNICODE FSS даже 256-символьный столбец будет иметь больший размер - потенциально 770 байт- как для хранения данных, так и для поиска. Дальше в этой главе будет много сказано об осторожности, которую вы должны проявить, решая вопрос о хранении текстов для многобайтовых наборов символов.