Один из эффективных способов разработки на
PL/pgSQL заключается в использовании предпочтительного текстового редактора для написания функций и вызове в другом окне утилиты
psql для загрузки и тестирования этих функций.
При таком подходе
целесообразно создавать функции с помощью команды CREATE OR
REPLACE FUNCTION. В этом случае для обновления определения функции достаточно повторно загрузить файл. Например:
CREATE OR REPLACE FUNCTION testfunc(integer) RETURNS integer AS $$
....
$$ LANGUAGE plpgsql;
Во время работы в psql, загрузить или перезагрузить такой файл с определением функции можно с помощью команды:
\i filename.sql
после чего можно сразу выполнять команды SQL для тестирования функции.
Другим эффективным способом разработки на языке PL/pgSQL является использование графического инструмента доступа к базам данных, упрощающего разработку на процедурном языке. Одним из примеров такого инструмента является pgAdmin, хотя существуют и другие аналоги. Такие инструменты часто предоставляют удобные функции, такие как экранирование одинарных кавычек, и упрощают процесс пересоздания и отладки функций.
Код PL/pgSQL функции указывается в
CREATE FUNCTION в виде строкового литерала. Если строковый литерал записывается обычным способом в одинарных кавычках, то все одинарные кавычки внутри тела функции должны быть удвоены; также должны быть удвоены все обратные косые черты (при условии использования синтаксиса escape-строк). Удвоение кавычек в лучшем случае утомительно, а в более сложных случаях код может стать совершенно непонятным, так как может потребоваться использование шести или более кавычек подряд. Вместо этого рекомендуется записывать тело функции в виде
«экранированная долларами,» представляет собой строковый литерал (см. Раздел 2.1.1.2.4). При использовании экранирования долларами никогда не требуется удваивать кавычки; вместо этого следует выбирать различные разделители для каждого необходимого уровня вложенности. Например, команду CREATE
FUNCTION можно записать следующим образом:
CREATE OR REPLACE FUNCTION testfunc(integer) RETURNS integer AS $PROC$
....
$PROC$ LANGUAGE plpgsql;
При этом кавычки можно использовать для простых строковых литералов в
командах SQL и $$ для разграничения фрагментов команд SQL, собираемых в виде строк. Если необходимо заключить в кавычки текст, который
содержит $$, можно использовать $Q$, и так далее.
В следующей таблице показано, какие действия необходимо выполнить при написании кавычек без использования экранирования долларами. Данная возможность может быть полезна при преобразовании кода, написанного без использования экранирования долларами, в более понятный вид.
Для обозначения начала и конца тела функции, например:
CREATE FUNCTION foo() RETURNS integer AS '
....
' LANGUAGE plpgsql;
В любом месте внутри тела функции, заключенного в одинарные кавычки, знаки кавычек необходимо должны дублироваться.
Для строковых литералов внутри тела функции, например:
a_output := ''Blah''; SELECT * FROM users WHERE f_name=''foobar'';
При использовании экранирования долларами можно написать так:
a_output := 'Blah'; SELECT * FROM users WHERE f_name='foobar';
что в точности соответствует тому, что PL/pgSQL анализатор увидит в любом случае.
Когда требуется использовать одиночную кавычку в строковой константе внутри тела функции, например:
a_output := a_output || '' AND name LIKE ''''foobar'''' AND xyz''
Значение, которое фактически будет добавлено к a_output будет таким:
AND name LIKE 'foobar' AND xyz.
При использовании экранирования долларами следует написать:
a_output := a_output || $$ AND name LIKE 'foobar' AND xyz$$
необходимо следить за тем, чтобы любые ограничители экранирования долларами вокруг этого не представляли собой $$.
Когда одиночная кавычка в строке внутри тела функции примыкает к концу этой строковой константы, например:
a_output := a_output || '' AND name LIKE ''''foobar''''''
Значение, добавляемое к a_output будет следующим:
AND name LIKE 'foobar'.
При использовании подхода с экранированием долларами это примет вид:
a_output := a_output || $$ AND name LIKE 'foobar'$$
Если в строковой константе требуется использовать две одиночные кавычки (что дает 8 кавычек) и они примыкают к концу этой строковой константы (еще 2). Это может потребоваться только при написании функции, генерирующей другие функции, как в Пример 5.6.10. Например:
a_output := a_output || '' if v_'' ||
referrer_keys.kind || '' like ''''''''''
|| referrer_keys.key_string || ''''''''''
then return '''''' || referrer_keys.referrer_type
|| ''''''; end if;'';
Значение a_output в таком случае будет следующим:
if v_... like ''...'' then return ''...''; end if;
При использовании подхода с экранированием долларами это примет вид:
a_output := a_output || $$ if v_$$ || referrer_keys.kind || $$ like '$$
|| referrer_keys.key_string || $$'
then return '$$ || referrer_keys.referrer_type
|| $$'; end if;$$;
где предполагается, что необходимо добавить только одинарные кавычки в
a_output, так как перед использованием это значение будет повторно заключено в кавычки.
Для помощи в поиске простых, но распространенных проблем до того, как они приведут к ошибкам, PL/pgSQL предоставляет дополнительные
проверки. Если они включены, то в зависимости от конфигурации их можно использовать для вывода либо сообщения WARNING либо сообщения ERROR
во время компиляции функции. Функция, получившая параметр a WARNING может быть выполнена без вывода последующих сообщений,
поэтому рекомендуется проводить тестирование в отдельной среде разработки.
Установка параметров plpgsql.extra_warnings, или
plpgsql.extra_errors, в зависимости от необходимости, в значение "all"
рекомендуется в средах разработки и тестирования.
Данные дополнительные проверки включаются с помощью переменных конфигурации
plpgsql.extra_warnings для предупреждений и
plpgsql.extra_errors для ошибок. Для обоих параметров можно установить значение в виде списка проверок через запятую, "none" или
"all". Значение по умолчанию — "none". В настоящее время
список доступных проверок включает:
shadowed_variables #Проверка того, не перекрывает ли объявление ранее определенную переменную.
strict_multi_assignment #
Некоторые PL/pgSQL команды позволяют присваивать
значения нескольким переменным одновременно, например
SELECT INTO. Как правило, количество целевых
переменных и количество исходных переменных должны совпадать, хотя
PL/pgSQL будет использоваться NULL
для недостающих значений, а лишние переменные будут проигнорированы. Включение этой
проверки приведет к тому, что PL/pgSQL будет выдаваться сообщение
WARNING или ERROR в случаях, когда
количество целевых переменных и количество исходных переменных
не совпадают.
too_many_rows #
Включение этой проверки позволит PL/pgSQL для
проверять, возвращает ли заданный запрос более одной строки, когда
INTO используется предложение. В качестве INTO
оператор всегда использует только одну строку, поэтому возврат запросом нескольких
строк обычно является либо неэффективным, либо недетерминированным и,
следовательно, скорее всего, считается ошибкой.
В следующем примере показан результат установки параметра plpgsql.extra_warnings
в значение shadowed_variables:
SET plpgsql.extra_warnings TO 'shadowed_variables';
CREATE FUNCTION foo(f1 int) RETURNS int AS $$
DECLARE
f1 int;
BEGIN
RETURN f1;
END;
$$ LANGUAGE plpgsql;
WARNING: variable "f1" shadows a previously defined variable
LINE 3: f1 int;
^
CREATE FUNCTION
В приведенном ниже примере показаны последствия установки значения
plpgsql.extra_warnings в
strict_multi_assignment:
SET plpgsql.extra_warnings TO 'strict_multi_assignment'; CREATE OR REPLACE FUNCTION public.foo() RETURNS void LANGUAGE plpgsql AS $$ DECLARE x int; y int; BEGIN SELECT 1 INTO x, y; SELECT 1, 2 INTO x, y; SELECT 1, 2, 3 INTO x, y; END; $$; SELECT foo(); WARNING: number of source and target fields in assignment does not match DETAIL: strict_multi_assignment check of extra_warnings is active. HINT: Make sure the query returns the exact list of columns. WARNING: number of source and target fields in assignment does not match DETAIL: strict_multi_assignment check of extra_warnings is active. HINT: Make sure the query returns the exact list of columns. foo ----- (1 row)