Элемент | Тип данных | Ограничения | TIMESTAMP/ диалект 1 DATE | DATE | TIME |
YEAR | SMALLINT | 0-5400 | Допустимо | Допустимо | Не допустимо |
MONTH | SMALLINT | 1-12 | Допустимо | Допустимо | Не допустимо |
DAY | SMALLINT | 1-31 | Допустимо | Допустимо | Не допустимо |
HOUR | SMALLINT | 0-23 | Допустимо | Не допустимо | Допустимо |
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() при нулевых датах.