Функция не найдена в PostgreSQL

У меня есть пользовательская функция в PostgreSQL 11.2, созданная следующим образом. Он в основном вставляет значения в две разные таблицы:

CREATE OR REPLACE FUNCTION public.insertTest(
IN ID1 integer, 
IN Value1 character varying,
IN Value2 character varying,
IN Value3 character varying,
IN Status character varying,
IN Active_Flag integer, 
IN Stuff1 smallint,
IN stuff2 smallint)
RETURNS void
LANGUAGE 'plpgsql'

AS $BODY$
BEGIN

Insert into TableA 
(TA_ID,
 TA_Value1, 
 TA_Value2,
 TA_Value3, 
 TA_Value4,
 TA_Time, 
 TA_Flag)
values 
(ID1,
 Value1, 
 Value2,
 Value3, 
 Status,
 now(), 
 1);

Insert into TableB
(TA_ID,
 TB_ID,      Confidence,     Sev_Rate, 
 Last_Update_Time,   TB_Flag)
values
(currval('tablea_t_id_seq'), --TableA has an auto-increment field
 Active_Flag,    Stuff1,     Stuff2,
 now(), 
 0);

END;
$BODY$;

Теперь, когда я пытаюсь выполнить эту функцию, не работает следующее:

SELECT * FROM public.insertTest (
550, 'Test_Value1', 
'Test_Value2', 'Test_Value3', 
'DEL', 55, 1, 1)

и выдает эту ошибку:

ERROR:  function insertTest(integer, unknown, unknown, unknown, unknown, integer, integer, integer) does not exist
LINE 1: select insertTest(550,'Test_Value1', 'Test_...
               ^
HINT:  No function matches the given name and argument types. You might need to add explicit type casts.

Но работает следующее:

SELECT * FROM public.insertTest (
550::integer, 'Test_Value1'::character varying, 
'Test_Value2'::character varying, 'Test_Value3'::character varying, 
'DEL'::character varying, 55::integer, 1::smallint, 1::smallint);

Может кто-нибудь сказать мне, почему 1-е выполнение функции не работает?


person P_Ar    schedule 14.08.2019    source источник


Ответы (2)


Может кто-нибудь сказать мне, почему 1-е выполнение функции не работает?

Точный ответ: Разрешение типа функции.

Столбцы varchar не являются проблемой (в отличие от другого ответа). Строковые литералы (с одинарными кавычками) изначально имеют тип unknown, и для этого существует неявное преобразование в varchar.

Столбцы int2 в конце - это "проблема" (точнее, несоответствие входных данных для них). Первоначально предполагается, что числовые литералы 1 (без кавычек!) имеют тип integer. И нет неявного приведения от integer (int4) к smallint (int2). Видеть:

SELECT castsource::regtype, casttarget::regtype, castcontext
FROM   pg_cast
WHERE  castsource = 'int'::regtype
AND    casttarget = 'int2'::regtype;

Руководство по castcontext:

e означает только явное приведение (с использованием синтаксиса CAST или ::). a означает неявно при присвоении целевому столбцу, а также явно. i означает неявно в выражениях, а также в других случаях

При явном приведении вызов функции завершается успешно:

SELECT * FROM pg_temp.insertTest (
550, 'Test_Value1', 
'Test_Value2', 'Test_Value3', 
'DEL', 55, int2 '1', int2 '1');

Или даже просто:

SELECT * FROM pg_temp.insertTest (
550, 'Test_Value1', 
'Test_Value2', 'Test_Value3', 
'DEL', 55,  '1', '1');

Теперь, с добавленными кавычками, это строковые литералы, изначально тип unknown, и для них существует неявное преобразование в int2.

db‹>скрипка здесь

Тесно связанные, с пошаговым объяснением:

person Erwin Brandstetter    schedule 19.08.2019

Как видно из сообщения об ошибке, PostgreSQL ожидает, что вы вызовете function insertTest(integer, unknown, unknown, unknown, unknown, integer, integer, integer). Все параметры типа character Variable не считаются таковыми, поэтому входные данные будут преобразованы в unknown.

Вы найдете адекватное объяснение в этой записи Stackoverflow (см. комментарии). К счастью, у вас уже есть потенциальное решение путем явного предоставления объявлений типов, по крайней мере, для ваших параметров character Variable.

person Spark Fountain    schedule 19.08.2019