Выполнение
функций
199
Для функций, возвращающих скалярные значения, любой синтаксис даст
идентичные результаты. Сложные типы рассматриваются позже в этой главе.
Также стоит отметить, что определяемые пользователем скалярные функ-
ции могут использоваться в запросах точно так же, как и встроенные функ-
ции. Вспомните функцию
text_to_numeric
из лис тинга 11.3. Вы можете спро-
сить, зачем создавать пользовательскую функцию преобразования,
когда
в PostgreSQL уже есть три разных способа преобразовать строку в целое чис-
ло. Для справки, вот эти три способа:
CAST
(text_value
AS
numeric)
;
text_value::numeric
– альтернативный синтаксис для
CAST
;
to_number(text_value,
'999999999999')
– с
использованием встроенной
функции.
Зачем нужна еще одна функция преобразования? Для любого из методов,
перечисленных в предыдущем списке, попытка преобразования приводит
к ошибке, если входная текстовая строка содержит символы, отличные от тех,
что могут встречаться в числах.
Чтобы функция преобразования не завершалась ошибкой, мы включаем
в тело функции
раздел
обработки
исключений
. Раздел начинается с ключево-
го слова
EXCEPTION
; ключевое слово
WHEN
может указывать конкретные типы
исключений. В этой главе мы будем использовать его только в форме
WHEN
OTHERS
, что соответствует всем типам исключений, не
включенным в пре-
дыдущие условия
WHEN
. Если, как в лис тинге 11.3,
конструкция
WHEN
OTHERS
используется сама по себе, это означает, что все исключения должны обра-
батываться одинаково.
В лис тинге 11.3 при ошибке преобразования (фактически при любой
ошибке) функция не завершится аварийно, а вернет неопределенное значе-
ние. Почему так важно, чтобы не происходил сбой, когда функции передается
«плохой» параметр? Потому что
она используется в списке
SELECT
.
В главе 7 мы создали материализованное представление
passenger_pass-
port
(см. лис тинг 7.11). Различные столбцы этого материализованного пред-
ставления должны содержать значения разных типов данных, но поскольку
в исходных данных все эти поля являются текстовыми, мы мало что можем
сделать. Если вы хотите выбрать номер паспорта как числовое значение, ваш
код может выглядеть так:
SELECT passenger_id,
passport_num::numeric AS passport_number
FROM passenger_passport
Если хотя бы в одной строке столбец
passport_num
содержит нечисловое
значение (например, пробел или пустую строку), то весь запрос завершит-
ся ошибкой. Вместо этого можно использовать
созданную нами функцию
text_to_integer
:
SELECT passenger_id,
text_to_numeric(passport_num) AS passport_number
FROM passenger_passport
Создадим еще одну пользовательскую функцию,
text_to_date
, которая пре-
образует строку, содержащую дату, в тип
date
, см. лис тинг 11.9.