Литералом (literal) называется значение, с которым не связан идентификатор; оно существует «само по себе». Несколько примеров литералов, которые могут встретиться в программе PL/SQL:
- Числа:
415, 21.6, 3.141592654f, 7D, NULL
- Строки:
'This is my sentence', '01-OCT-1986', q'!hello!', NULL
- Временные интервалы:
INTERVAL '25-6' YEAR TO MONTH, INTERVAL '-18' MONTH, NULL
- Логические значения:
TRUE, FALSE, NULL
Суффикс «f» в числовом литерале 3.14159f обозначает 32-разрядное вещественное число в стандарте IEEE 754, частично поддерживаемом Oracle, начиная с версии 10g Release 1. Аналогичным образом, 7D — число 7, представленное в 64-разрядном вещественном формате.
О строке q'!hello!' следует упомянуть особо. Знак ! — пользовательский ограничитель (возможность использования пользовательских ограничителей также появилась в Oracle10g). Начальная буква q и одинарные кавычки, в которые заключено значение, сообщают компилятору, что ! — ограничитель, а не часть значения, а строка содержит просто слово hello.
Тип данных INTERVAL предназначен для работы с интервалами между определенными датами или моментами времени. Первый интервал в приведенном выше примере означает «через 25 лет и еще 6 месяцев», а второй — «на 18 месяцев ранее».
Хотя интервалы могут задаваться в литеральном формате, для типов DATE такая возможность не предусмотрена; скажем, значение '01-OCT-1986' интерпретируется как строка, а не как тип Oracle DATE. Да, PL/SQL или SQL могут неявно преобразовать строку '01- OCT-1986' во внутренний формат даты Oracle1, но обычно в программном коде следует выполнять явные преобразования с использованием встроенных функций. Пример:
TO_DATE('01-OCT-1986', 'DD-MON-YYYY') TO_TIMESTAMP_TZ('01-OCT-1986 00:00:00 -6','DD-MON-YYYY HH24:MI:SS TZH')
Оба выражения возвращают время 00:00:00 1 октября 1986 года; первое относится к типу данных DATE, а второе — к типу данных временного штампа с часовым поясом. Во второе выражение также включена информация о часовом поясе (–6 — смещение в часах от общемирового времени GMT (UCT)).
В отличие от идентификаторов строковые литералы PL/SQL чувствительны к регистру символов. Как и следовало ожидать, следующие два литерала различаются:
'Steven' 'steven'
А проверка следующего условия возвращает FALSE:
IF 'Steven' = 'steven'
NULL
Отсутствие значения представляется в Oracle ключевым словом NULL. Как показано в предыдущем разделе, переменные почти всех типов данных PL/SQL могут существовать в состоянии NULL (исключение составляют только ассоциативные массивы, экземпляры которых всегда отличны от NULL). Правильная обработка переменных со значением NULL и так является непростой задачей для программиста, а NULL-строки вдобавок требуют особого обращения.
В Oracle SQL и PL/SQL NULL-строка обычно неотличима от литерала из нуля символов, буквально представляемого в виде '' (две одинарные кавычки, между которыми нет ни одного символа). Например, следующее условие равно TRUE как в SQL, так и в PL/SQL:
'' IS NULL
Если в PL/SQL переменной VARCHAR2(n) присваивается строка нулевой длины, то результат также считается равным NULL:
DECLARE str VARCHAR2(1) := ''; BEGIN IF str IS NULL -- равно TRUE
Такое поведение соответствует правилам обработки столбцов VARCHAR2 в таблицах баз данных.
Но с данными типа CHAR дело обстоит сложнее. Если создать в PL/SQL переменную типа CHAR(n) и присвоить ей строку нулевой длины, база данных дополняет пустую переменную пробелами, в результате чего она становится отличной от NULL:
DECLARE flag CHAR(2) := ''; -- CHAR(2) присваивается строка нулевой длины BEGIN IF flag = ' ' ... -- равно TRUE IF flag IS NULL ... -- равно FALSE
Как ни странно, такое поведение проявляется только в PL/SQL. В базе данных при вставке строки нулевой длины в поле типа CHAR(n) содержимое столбца не дополняется пробелами, а остается равным NULL!
В этих примерах проявляется частичная поддержка Oracle версий 92 и 99 стандарта ANSI SQL, согласно которому строка нулевой длины должна отличаться от NULL-строки. По утверждениям Oracle, стандарт будет полностью поддерживаться в будущих версиях. Впрочем, разговоры на эту тему идут уже 15 лет и пока этого не произошло.
База данных пытается неявно преобразовать NULL к типу значения, необходимому для текущей операции. Время от времени может возникнуть необходимость в выполнении явных преобразований с использованием синтаксических конструкций вида TO_NUMBER(NULL) или CAST(NULL AS NUMBER).
Одинарные кавычки внутри строки
Неприятная сторона работы со строковыми литералами проявляется тогда, когда вам нужно включить в строку одинарную кавычку. До выхода Oracle10g одна литеральная кавычка внутри строки обозначалась удвоением символа кавычки. Примеры:
Литерал (с ограничителем по умолчанию) | Фактическое значение |
'There''s no business like show business.' | There's no business like show business. |
'"Hound of the Baskervilles"' | "Hound of the Baskervilles" |
'''' | ' |
'''hello''' | 'hello' |
'''''' | '' |
Например, из этих примеров следует, что для представления литерала из двух одиночных кавычек требуется целых шесть символов. Для упрощения подобных конструкций в Oracle10g появились специальные ограничители. Литерал начинается с символа q, а выражение в ограничителях заключается в одиночные кавычки. В следующей таблице приведены примеры использования этого синтаксиса.
Литерал (со специальными ограничителями) | Фактическое значение |
q' ( There's no business like show business.) ' | There's no business like show business. |
q' { "Hound of the Baskervilles" } ' | "Hound of the Baskervilles" |
q' [ ' ] ' | ' |
q' !'hello' ! ' | 'hello' |
q' |'' | ' | '' |
Как видно из примеров, вы можете использовать как простые ограничители (!, | и т. д.), так и «парные»: левая и правая круглые, фигурные и квадратные скобки.
Напоследок следует заметить, что символ двойной кавычки в строковых литералах не имеет специального значения, а интерпретируется так же, как буква или цифра.
Числовые литералы
Числовые литералы могут быть целыми или действительными (то есть содержащими дробную часть) числами. Заметьте, что PL/SQL рассматривает число 154.00 как действительное, хотя его дробная часть равна нулю и с точки зрения математики оно является целым. Целые и действительные числа имеют разное внутреннее представление, и преобразование числа из одной формы в другую требует определенных ресурсов.
Для определения числовых литералов может использоваться экспоненциальная (научная) запись. Буква E (в верхнем или нижнем регистре) обозначает степень 10 (например, 3.05E19, 12e–5).
Начиная с версии Oracle Database 10g, вещественные числа могут представляться как типом Oracle NUMBER, так и стандартным типом IEEE 754 с плавающей точкой. К последней категории относятся типы BINARY (32-разрядное; обозначается суффиксом F) и BINARY DOUBLE (64 разрядное; обозначается суффиксом D).
В соответствии со стандартом IEEE, в некоторых выражениях могут использоваться именованные константы из следующей таблицы.
Описание | BINARY (32-разрядное) | BINARY DOUBLE (64-разрядное) |
«Не число» (NaN, Not a Number): результат деления на 0 или недействительной операции | BINARY_FLOAT_NAN | BINARY_DOUBLE_NAN |
Положительная бесконечность | BINARY_FLOAT_INFINITY | BINARY_DOUBLE_INFINITY |
Абсолютное наибольшее число, которое может быть представлено | BINARY_FLOAT_MAX_NORMAL | BINARY_DOUBLE_MAX_NORMAL |
Наименьшее нормальное число; порог потери значимости | BINARY_FLOAT_MIN_NORMAL | BINARY_DOUBLE_MIN_NORMAL |
Наибольшее положительное число, меньшее порога потери значимости | BINARY_FLOAT_MAX_SUBNORMAL | BINARY_DOUBLE_MAX_SUBNORMAL |
Абсолютное наименьшее число, которое может быть представлено | BINARY_FLOAT_MIN_SUBNORMAL | BINARY_DOUBLE_MIN_SUBNORMAL |
Логические (булевские) литералы
Для представления логических значений в PL/SQL определено два литерала: TRUE и FALSE. Это не строки и их не нужно заключать в кавычки. Они используются для присваивания значений логическим переменным, как в следующем примере:
DECLARE enough_money BOOLEAN; -- Объявление логической переменной BEGIN enough_money := FALSE; -- Присваивание значения END;
При проверке логического значения литерал можно не указывать — тип переменной говорит сам за себя:
DECLARE enough_money BOOLEAN; BEGIN IF enough_money THEN ...
Логическое выражение, переменная или константа также могут быть равны NULL — неопределенному значению, которое не является ни TRUE, ни FALSE.