Иногда возникает ошибка, подобная этой:
ERROR: type of parameter 6 (numeric) does not match that when preparing the plan (integer)
CONTEXT: PL/pgSQL function inline_code_block line 15 at RAISE
и найти причины её возникновения бывает не так просто.
Причина же почти в 100% процентах случаев кроется в динамических запросах и обработке их результатов.
Вот пример кода, при выполнении которого возникает ошибка:
DO $$
DECLARE
_rec record;
_i integer;
_query text;
BEGIN
FOR _i IN 1..2
LOOP
IF _i = 1 THEN
_query := 'SELECT 1::int AS value';
ELSE
_query := 'SELECT 1::numeric AS value';
END IF;
EXECUTE _query INTO _rec;
RAISE LOG '%', _rec.value; -- ошибка возникает во время второго прохода
END LOOP;
END
$$;
Причина кроется в том, как PL/pgSQL интерпретатор выполняет код. При первом обращении в сессии к функции интерпретатор строит дерево инструкций, а при первом выполнении инструкции "кэширует план её выполнения", учитывая тип переменных. При повторном обращении к данной инструкции (выражению) интерпретатор использует уже закэшированный план её выполнения. И если тип переменных по какой-либо причине изменился, то генерируется ошибка. При использовании простых переменных такой ошибки быть не может, так как тип переменной не может быть изменен в рамках выполнения хранимой процедуру. При использовании же изменяемых типов, к которым относится record, такие ошибки вполне вероятны.
Будьте бдительны!