I have a user-defined function in PostgreSQL 11.2 created as follows. It basically inserts values to two different tables:
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$;
Now when I try to execute this function, the following does not works:
SELECT * FROM public.insertTest (
550, 'Test_Value1',
'Test_Value2', 'Test_Value3',
'DEL', 55, 1, 1)
and throws this error:
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.
But the following works:
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);
Can someone tell me why the 1st execution of the function does not work?
... why the 1st execution of the function does not work?
The exact answer is: Function Type Resolution.
The varchar
columns are not the problem (unlike another answer suggests). String literals like 'Test_Value1'
(with single quotes) are initially type unknown
and there is an implicit conversion to varchar
for that.
The int2
columns at the end are the "problem" (or rather, the mismatched input for those). Numeric literals like 1
(without quotes!) are initially assumed to be type integer
. And there is no implicit cast from integer
(int4
) to smallint
(int2
). See:
SELECT castsource::regtype, casttarget::regtype, castcontext
FROM pg_cast
WHERE castsource = 'int'::regtype
AND casttarget = 'int2'::regtype;
Reveals castcontext = 'a'
. The manual about castcontext
:
e
means only as an explicit cast (usingCAST
or::
syntax).a
means implicitly in assignment to a target column, as well as explicitly.i
means implicitly in expressions, as well as the other cases
With an explicit cast, the function call succeeds:
SELECT * FROM pg_temp.insertTest (
550, 'Test_Value1',
'Test_Value2', 'Test_Value3',
'DEL', 55, int2 '1', int2 '1');
Or even just:
SELECT * FROM pg_temp.insertTest (
550, 'Test_Value1',
'Test_Value2', 'Test_Value3',
'DEL', 55, '1', '1');
Now, with added quotes, those are string literals, initially type unknown
, and there is an implicit conversion to int2
for those.
Closely related, with step-by-step explanation: