Объявить переменную set = select
Возможно, это звучит как очень глупый вопрос, но как мне объявить переменную для использования в запросе PostgreSQL 9.3?
CREATE or replace FUNCTION public.test()
returns int4
AS
$BODY$
DECLARE
cod_process bigint :=30001;
cod_instance bigint ;
utc_log timestamp without time zone := localtimestamp;
cod_log_type varchar(100) :='information ';
txt_log_text varchar(100):= 'start process';
txt_log varchar(100):= txt_log_text||'_'||cod_process;
set cod_instance= select max(cod_instance) as cod_instance from public.instance where public.instance.cod_process=cod_process;
BEGIN
INSERT INTO public.log (cod_process, cod_instance, utc_log,cod_log_type,txt_log)
VALUES (cod_process, cod_instance, utc_log,cod_log_type,txt_log );
RETURN 11;
END;
$BODY$ LANGUAGE 'plpgsql';
ERROR: type "cod_instance" does not exist SQL state: 42704 Character: 383
2 ответа
Вам нужно запустить выбор, используя into
предложение внутри фактического блока кода, а не в declare
блок:
begin
select max(cod_instance)
into cod_instance
from public.instance
where public.instance.cod_process=cod_process;
....
end;
Обычно не очень хорошая идея давать переменным (или параметрам) то же имя, что и столбцам в таблице. Есть определенные случаи, когда это может запутать парсер. Чтобы избежать каких-либо потенциальных проблем, попробуйте использовать разные имена для ваших переменных, например, с помощью префикса их (например, l_cod_process
вместо cod_process
или же l_cod_instance
вместо cod_instance
)
Более подробную информацию о назначении переменных можно найти в руководстве: http://www.postgresql.org/docs/current/static/plpgsql-statements.html
Ваша демонстрационная функция будет работать так:
CREATE or replace FUNCTION public.test()
RETURNS int4 AS
$func$
DECLARE
_cod_process bigint := 30001;
_cod_instance bigint := (SELECT max(cod_instance)
FROM public.instance
WHERE cod_process = _cod_process);
_utc_log timestamp := localtimestamp;
_cod_log_type varchar(100) := 'information';
_txt_log_text varchar(100) := 'start process';
_txt_log varchar(100) := txt_log_text || '_' || cod_process;
BEGIN
INSERT INTO public.log
( cod_process, cod_instance, utc_log, cod_log_type, txt_log)
VALUES (_cod_process, _cod_instance, _utc_log, _cod_log_type, _txt_log);
RETURN 11;
END
$func$ LANGUAGE plpgsql;
Основные моменты
Вы не можете использовать
SET
назначить переменную. Это принято за команду SQLSET
для настройки параметров времени выполнения.Но вы можете назначить переменную во время объявления, даже использовать для этого подзапрос.
использование
LANGUAGE plpgsql
неLANGUAGE 'plpgsql'
, Это идентификатор.@a_horse_with_no_name уже писал о конфликтах имен.
Использование чистого формата имеет большое значение при отладке кода...
Но вы можете, вероятно, упростить до:
CREATE OR REPLACE FUNCTION public.test(_cod_process bigint = 30001)
RETURNS integer AS
$func$
INSERT INTO public.log
(cod_process, cod_instance , utc_log, cod_log_type , txt_log)
SELECT $1, max(cod_instance), now() , 'information', 'start process_' || $1
FROM public.instance
WHERE cod_process = $1
GROUP BY cod_process
RETURNING 11
$func$ LANGUAGE sql;
Вызов:
SELECT public.test(); -- for default 30001
SELECT public.test(1234);
И в зависимости от фактического типа данных utc_log
ты наверное хочешь now() AT TIME ZONE 'UTC'
: