Шрифт:
Интервал:
Закладка:
Например, совершенно верным является затребовать, чтобы запрос SELECT вернул константу, которая не связана ни с каким столбцом в базе данных. Основное "хакерство" в Firebird- использование системной таблицы RDB$DATABASE в запросе, поскольку эта таблица имеет одну и только одну строку, и всегда можно получить скалярное значение: единственное контекстное значение от сервера. Следующие два примера иллюстрируют типичное использование этого приема:
SELECT 'NOW' FROM RDB$DATABASE;
Так как запрос возвращает константу, а не значение столбца, ее тип данных интерпретируется как CHAR(3), 'NOW'. Этот пример
SELECT '2.09.2004' FROM RDB$DATABASE;
вернет CHAR(9), '2.09.2004'.
Чтобы получить от синтаксического анализатора правильную интерпретацию литерала даты при условии, что анализатор не может определить тип данных, используйте функцию CAST():
* для диалекта 3:
SELECT CAST('NOW' AS TIMESTAMP) FROM RDB$DATABASE;
SELECT CAST('2.09.2004' AS TIMESTAMP) FROM RDB$DATABASE;
* для диалекта 1:
SELECT CAST('NOW' AS DATE) FROM RDB$DATABASE;
SELECT CAST('2.09.2004' AS DATE) FROM RDB$DATABASE;
Контекстные переменные даты и времени
Контекстные переменные даты и времени CURRENT_DATE, CURRENT_TIME и CURRENT_TIMESTAMP возвращают значение даты и времени, полученные с сервера на момент начала выполнения оператора SQL, содержащего контекстную переменную. Табл. 10.6 описывает эти переменные.
Таблица 10.6. Контекстные переменные даты и времени
Переменная
Тип диалекта 3
Тип диалекта 1
Значение
CORRENT_TIMESTAMP
TIMESTAMP
DATE
Текущая дата и время, округленное до секунд. Дробная часть секунд всегда возвращается равной '.0000'
CURRENT_DATE
DATE
Не поддерживается
Текущая дата
CURRENT_TIME
TIME
Не поддерживается
Текущее время, выраженное в часах, минутах и секундах после полуночи. Дробная часть секунд всегда возвращается равной ' .0000'
Операции, использующие значения даты и времени
Использование арифметических операций в манипулировании данными, в вычислениях и в отношениях между двумя датами были ранее рассмотрены в разд. "Интервал времени" этой главы. Возможность вычитания значения более ранней даты, времени или даты-времени из более поздней существует благодаря способу хранения типов дата и время в Firebird. Способ хранения использует одно или два 32-битовых целых для даты/времени, только для даты или только для времени дня. Данные, представленные в этих числах, являются днями в длинном слове даты и дробной частью дней в слове времени. Дата представлена количеством дней с "нулевой даты"- 17 ноября 1898 г[26]. Время представлено в десятитысячных долях секунд, прошедших с полуночи.
В диалекте 3 DATE хранит только дату. В диалекте 3 TIME хранит только время. TIMESTAMP и в диалекте 1 DATE хранят обе части.
С этими числовыми структурами можно довольно просто оперировать, используя несложные выражения сложения и вычитания для вычисления разницы во времени (интервал), увеличения или уменьшения дат, установления диапазонов даты или времени. В табл. 10.7 описываются доступные операции и получаемые результаты.
Таблица 10.7. Арифметические операции для типов данных даты и времени
Операнд 1
Оператор
Операнд 2
Результат
DATE
+
TIME
TIMESTAMP (арифметическая конкатенация)
DATE
+
Числовое значение n**
DATE, увеличенная на n целых дней (игнорируется дробная часть n, если указана)
TIME
+
DATE
TIMESTAMP (арифметическая конкатенация)
TIME
+
Числовое значение n**
TIME, увеличенное на n секунд*
TIMESTAMP
+
Числовое значение n**
TIMESTAMP, где дни увеличены на целую часть числа n плюс дробная часть числа n (если указана) как количество десятитысячных долей секунды в дне (8.64 x 10(^5^))
DATE
-
DATE
Количество дней в интервале: DECIMAL(9,0)
DATE
-
Числовое значение N**
DATE, уменьшенная на n дней (игнорируется дробная часть n, если указана)
TIME
-
TIME
Количество секунд в интервале: DECIMAL(9,4)
TIME
-
Числовое значение n**
TIME, уменьшенное на n секунд*
TIMESTAMP
-
TIMESTAMP
Количество дней и части дня в интервале: DECIMAL (18, 9)
TIMESTAMP
-
Числовое значение n**
TIMESTAMP, где дни уменьшены на целую часть числа n плюс дробная часть числа n (если указана) как количество десятитысячных долей секунды в дне (8.64x10(^5^))
* При необходимости повторяется (result=modulo(result, (24*60*60))) пока не будет выделена результирующая часть дней.
** В диалекте 3 для типа DATE n является целым, представляющим количество дней. Для типов данных TIMESTAMP и для диалекта 1 DATE n может быть числом, представляющим количество дней слева от десятичной точки (целая часть) и части дня справа от десятичной точки (дробная часть). Для типа TIME n является целым числом, представляющим количество секунд.
Общие правила для операций
Одно значение даты или времени может быть вычтено из другого, если:
* оба значения имеют один и тот же тип даты/времени;
* первый операнд является более поздним, чем второй.
Вычитание, использующее типы дата/время, дает результаты: масштабируемое DECIMAL в диалекте 3 и DOUBLE PRECISION В диалекте 1.
Типы данных дата/время не могут складываться друг с другом. Однако можно выполнить конкатенацию части даты и части времени, используя:
* дополнительный бинарный синтаксис для конкатенации пар полей или переменных;
* объединение строк для конкатенации литерала дата/время с другим литералом дата/время или с полем, или переменной типа дата/время.
Операции умножения и деления, включающие типы данных дата/время, недопустимы.
Выражения в качестве операндов
Операндом при увеличении или уменьшении значения TIMESTAMP, TIME, DATE или DATE в диалекте 1 может быть константа или выражение. Выражение может быть особенно полезным в ваших приложениях, когда вам надо увеличить или уменьшить значение в секундах, минутах, часах или, например, требуется половина дня, а не целое количество дней.
Диалект 3 использует правило SQL-92 для деления целого на целое: результатом всегда будет целое, округленное при необходимости в меньшую сторону. При использовании выражений в диалекте 3 убедитесь, что один из операндов является действительным числом с достаточным количеством десятичных знаков, чтобы избежать возможной арифметической ошибки или потери точности результата при выполнении целочисленного деления SQL-92.
В табл. 10.8 показаны некоторые примеры.
Таблица 10.8. Примеры использования выражений в качестве операндов
Вводимый операнд n
Сложение или вычитание
Альтернатива
В секундах
n/86400.0
(n*1,0)/(60* 60*24)
В минутах
n/1440.0
(n*1.0)/(60*24)
В часах
n/24.0
Зависит от желаемого результата. Например, если n=3, а делитель для половины дня - 2, результат будет 1, а не 1.5
Половина дня
n/2
То же
Поскольку годы, месяцы, кварталы не являются константами, нужны более сложные алгоритмы для их использования в операциях даты/времени. Возможно, вам следует для этих целей посмотреть функции, определенные пользователем (UDF), которые вы сможете использовать в качестве выражений в операндах.
Использование CAST() с типами дата/время
В некоторых местах этой главы вы встречали функцию CAST() в выражениях, содержащих типы данных даты и литералы даты. В настоящем разделе рассматриваются различные аспекты преобразования даты и времени более широко и подробно.
Преобразование между типами дата/время
Обычно преобразование из одного типа дата/время в другой возможно, если исходный тип дата/время содержит подходящий вид данных для помещения в выходной тип дата/время. Например, TIMESTAMP содержит данные, которые можно преобразовать в тип только даты DATE или только время TIME, В то время как тип TIME не содержит достаточно данных для преобразования в тип DATE. Firebird предоставляет возможность преобразовывать тип DATE В TIMESTAMP, присваивая времени значение полночи, и тип TIME в TIMESTAMP, выбирая дату из контекстной переменной CURRENT_DATE (серверное время). В табл. 10.9 представлены правила преобразования.
Таблица 10.9. Преобразования между типами дата/время в диалекте 3
Исходный тип
В тип TIMESTAMP
В тип DATE
В тип TIME
TIMESTAMP
Недоступно
Да, преобразует дату, игнорируя время
Да, преобразует время, игнорируя дату
- Delphi. Учимся на примерах - Сергей Парижский - Программирование
- Сделай видеоигру один и не свихнись - Слава Грис - Программирование / Руководства
- Психбольница в руках пациентов - Алан Купер - Программирование