How to execute a stored procedure directly in postgresql? - postgresql

I have created a procedure like :
CREATE OR REPLACE FUNCTION insert_user_ax_register(
user_name character varying(50),
password character varying(300),
role_id character varying(10),
created_dt date,
status boolean,
email character varying(50),
join_date character varying(30),
phone_no bigint,
client_address character varying(200),
full_name character varying(100),
financial_year character varying(10))
RETURNS void
AS $BODY$
declare
begin
INSERT INTO ax_register(user_name,password,role_id,created_dt,status,email,join_date,phone_no,client_address,full_name,financial_year)
VALUES (user_name,password,role_id,now(),true,email,join_date,phone_no,client_address,full_name,financial_year);
end
$BODY$
LANGUAGE plpgsql VOLATILE
and tried to execute it like this:
SELECT * from insert_user_ax_register('debasrita','debasrita','client001',now(),'t','abc#gmail.com',now(),'ctc','debasrita','2014-15',9090909090);
but it throws the following error :
ERROR: function insert_user_ax_register(unknown, unknown, unknown, timestamp with time zone, unknown, unknown, timestamp with time zone, unknown, unknown, unknown, bigint) does not exist
SQL state: 42883
Hint: No function matches the given name and argument types. You might need to add explicit type casts.
Character: 16
Please help me out on this. I am new to pgsql and not able to find out any solution from google. I am using pgsql 9.1.3
May I know what is the correct way to achieve my objective?

The error message tells you what you need to be looking for:
"No function matches the given name and argument types"
As the function name seems correct, it can only be the parameters you are passing. So write down which value is passed for which parameter:
'debasrita' --> user_name character varying(50)
'debasrita' --> password character varying(300)
'client001' --> role_id character varying(10)
created_dt date --> now()
status boolean, --> 't'
email varchar(50) --> 'abc#gmail.com'
join_date varchar(30) --> now() << first error: now() is not a character constant
phone_no bigint --> 'ctc' << second error: 'ctc' is not a bigint
client_address varchar(200) --> 'debasrita'
full_name varchar(100) --> '2014-15'
financial_year varchar(10) --> 9090909090 << third error: 9090909090 is not a character literal
So you need to either adjust the parameter types, e.g. define join_date as date, not as varchar or adjust the values that you pass for each parameter.
And finally you need to call the function like this:
SELECT insert_user_ax_register(...);
rather than select * from ...

If you are using pgAdmintool just right click on the function or Stored Proc under a schema and select properties and then paramaeters .Now insert the value which you wannna insert.

Related

Structure of query does not match function result type in plpgsql function

CREATE
OR REPLACE FUNCTION public.sp_production_snapshot(periodid integer, flagdc integer) RETURNS TABLE(
prod_period_id integer,
period character varying,
nosp character varying,
policy_no character varying,
policy_name character varying,
status_id integer,
pol_status character varying,
family_bisnis character varying,
tahun_ke integer,
year_comm integer,
payment integer,
plan_code character varying,
life_premium double precision,
rider_premium double precision,
extra_premium double precision,
total_premium double precision,
mop integer,
ccy_code character varying,
ccy_rate double precision,
post_date date,
commence_date date,
issue_date date,
stream_start_date date,
due_date date,
app_code character varying,
policy_cat character varying,
apcrd_a_amt double precision,
apcrd_b_amt double precision,
apcrd_d_amt double precision,
fyip_credit_amt double precision,
comm_npk_id integer,
comm_npk integer,
comm_npk_name character varying,
comm_rank_id integer,
comm_rank_code integer,
comm_rank_name character varying,
) LANGUAGE plpgsql AS $function$ BEGIN RETURN QUERY . . . . . . . . .
;
When I'm running it like this:
select * from sp_production_snapshot(865, 1);
I get the error:
SQL Error [42804]: ERROR: structure of query does not match function result type
Detail: Returned type bigint does not match expected type integer in column 1.
Where: PL/pgSQL function sp_production_snapshot(integer,integer) line 3 at RETURN QUERY
What is wrong with my script? I just migrated from gorm v1 to gorm v2. Before everything was fine, but many things break after moving to gorm v2.
Your statement after RETURN QUERY in the function body is likely selecting an identifier defined as bigint/bigserial type. It's not always safe to assume that this bigint value will map to your output integer because bigint can accommodate a higher values than integer can. From the documentation:
integer can be anything from -2147483648 to +2147483647
bigint can go from -9223372036854775808 to +9223372036854775807
bigserial can go from +1 to +9223372036854775807
If you stumbled upon a prod_period_id of 2147483648, you'd get an ERROR: integer out of range. To fix this you need to change the output types of your function accordingly:
DROP FUNCTION public.sp_production_snapshot(integer,integer);
CREATE FUNCTION public.sp_production_snapshot(
periodid integer, --should be bigint too if it corresponds to prod_period_id
flagdc integer)
RETURNS TABLE(
prod_period_id bigint,--change from integer to bigint
period character varying,
...
Depending on the structure of your RETURN QUERY and its sources, it's likely that it won't be the only output integer value you'll have to change to bigint. Note that you'll have to furst DROP then re-CREATE the function to avoid ERROR: cannot change return type of existing function thrown if you tried CREATE OR REPLACE instead.
If your output table follows the structure of some other table, instead of copying that into the function output table definition, you can use LIKE syntax:
DROP FUNCTION public.sp_production_snapshot(integer,integer);
CREATE FUNCTION public.sp_production_snapshot(
periodid integer,
flagdc integer)
RETURNS TABLE (LIKE your_table_schema.your_table_name) as
$function$
...
$function$ language plpgsql;
or RETURNS SETOF:
DROP FUNCTION public.sp_production_snapshot(integer,integer);
CREATE FUNCTION public.sp_production_snapshot(
periodid integer,
flagdc integer)
RETURNS SETOF your_table_schema.your_table_name language plpgsql as
$function$
...
$function$;
Also, if all you do is return a query, without using PL/pgSQL variables, loops, exception handling, you can stick with plain LANGUAGE SQL for better performance thanks to inlining. If all it does is look things up elsewhere, without modifying anything, it might be worth it to also make it STABLE and PARALLEL SAFE to enable better optimisation and execution planning.
DROP FUNCTION public.sp_production_snapshot(integer,integer);
CREATE FUNCTION public.sp_production_snapshot(
periodid integer,
flagdc integer)
RETURNS SETOF your_table_schema.your_table_name
STABLE PARALLEL SAFE LANGUAGE SQL AS
$function$
SELECT * FROM your_table_schema.your_table_name AS a
WHERE a.prod_period_id = $1 AND a.flagdc = $2;
$function$;

plpgsql: No function matches the given name and argument types. You might need to add explicit type casts

I've created a stored procedure in PostgreSQL using DBeaver.
& I'm trying to insert data into table by calling the procedure from DBeaver.
But it's giving me an error
SQL Error [42883]: ERROR: function public.proc_insert_test(integer, unknown, unknown, unknown, unknown, timestamp with time zone, integer, integer, integer, timestamp with time zone) does not exist
Hint: No function matches the given name and argument types. You might need to add explicit type casts.
Position: 8
Procedure:
CREATE OR REPLACE FUNCTION public.proc_insert_test(p_brndcode integer,
p_brndname varchar(100),
p_brndsname varchar(100),
p_prdtype char(1),
p_discontinue char(1),
p_crddate date,
p_status integer,
p_recstat integer,
p_brndgrpseqno integer,
p_wefrom date)
RETURNS char
LANGUAGE plpgsql
AS $body$
BEGIN
Insert into arc_mmstbrndgroup(brndcode, brndname, brndsname, prdtype, discontinue, crddate, status, recstat, brndgrpseqno, wefrom)
values(p_brndcode, p_brndname, p_brndsname, p_prdtype, p_discontinue, p_crddate, p_status, p_recstat, p_brndgrpseqno, p_wefrom);
END;
$body$
;
Calling the procedure:
select public.proc_insert_test(123, 'Test2', 'Test2', 'T', 'T', now(), 1, 9, 1234, now());
What can be the issue?
I'm totally new to this.
Update:
Procedure calling:
select public.proc_insert_test(123, 'Test2'::varchar(100), 'Test2'::varchar(100), 'T'::char(1), 'T'::char(1), now(), 1, 9, 1234, now());
Error:
SQL Error [42883]: ERROR: function public.proc_insert_test(integer, character varying, character varying, character, character, timestamp with time zone, integer, integer, integer, timestamp with time zone) does not exist
Hint: No function matches the given name and argument types. You might need to add explicit type casts.
Position: 8
Postgres doesn't allow implicit conversion from timestamp to date data type. Attention - Postgres date type is different from Oracle's date type.
CREATE OR REPLACE FUNCTION public.test(v date)
RETURNS void
LANGUAGE plpgsql
AS $function$
BEGIN
RAISE NOTICE '%', v;
END;
$function$
postgres=# SELECT test(now());
ERROR: function test(timestamp with time zone) does not exist
LINE 1: SELECT test(now());
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
postgres=# SELECT test(current_date);
NOTICE: 2019-11-14
+------+
| test |
+------+
| |
+------+
(1 row)
postgres=# SELECT test(now()::date);
NOTICE: 2019-11-14
+------+
| test |
+------+
| |
+------+
(1 row)
The conversion from timestamp (result type of now() function) to date is losing conversions. It is not allowed by default. So you should to enforce it (by explicit casting), or you should to use pseudo constant current_date that returns date type, and there is not necessary any conversion.

Function not found in PostgreSQL

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?
Can someone tell me 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 (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). The numeric literals 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;
The manual about castcontext:
e means only as an explicit cast (using CAST 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.
db<>fiddle here
Closely related, with step-by-step explanation:
No function matches the given name and argument types
Is there a way to disable function overloading in Postgres
As you can see from the error message, PostgreSQL expects that you call function insertTest(integer, unknown, unknown, unknown, unknown, integer, integer, integer). All parameters of type character varying are not regarded as such and therefore the inputs will be cast to unknown.
You'll find an adequate explanation in this Stackoverflow post (look at the comments). Fortunately, you already have a potential solution by providing type declarations explicitly, at least for your character varying parameters.

function does not exists in postgreSQL .. Why ?

Need your help please , can't understand why i got the following error , i am not a professional postgresql developer ..
As you can see the function created , so why the function not exist occurred ?
create or replace function loginAttempt (u_email character varying, u_password character varying, date_time timestamptz, OUT attempt smallint) returns smallint AS $$
BEGIN
INSERT INTO login_attempts (typed_password, date_time, attempt_nu, email) VALUES (u_password, date_time, attempt_nu, email);
IF attempt = 3 THEN INSERT INTO warnings (u_email,u_password) VALUES (u_email,u_password);
END IF;
END;
$$ LANGUAGE plpgsql;
select loginattempt ('Jon.Jones88#gmail.com','+_#kjhfdb987', now(), 1);
ERROR: function loginattempt(unknown, unknown, timestamp with time zone, integer) does not exist
LINE 1: select loginattempt ('Jon.Jones88#gmail.com','+_#kjhfdb987',...
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
SQL state: 42883
Character: 8
You have defined the last parameter as an OUT parameter, that means you can't pass a value for it.
You need to use:
select loginattempt ('Jon.Jones88#gmail.com','+_#kjhfdb987', now());
As you are not writing to the parameter attempts I don't see a reason to define it as an out parameter to begin with. You can simply return the value if you need it:
create or replace function loginAttempt (u_email character varying, u_password character varying, u_date_time timestamptz, u_attempt smallint)
returns smallint
AS $$
BEGIN
INSERT INTO login_attempts (typed_password, date_time, attempt_nu, email)
VALUES (u_password, u_date_time, u_attempt, u_email);
IF u_attempt = 3 THEN
INSERT INTO warnings (u_email,u_password) VALUES (u_email,u_password);
END IF;
return u_attempt;
END;
$$ LANGUAGE plpgsql;
As the value 1 is assumed to be an integer, you need to cast that value when calling the function:
select loginattempt ('Jon.Jones88#gmail.com','+_#kjhfdb987', now(), 1::smallint);
Online example: https://rextester.com/YNIQ55561

PostgreSQL - Invalid input syntax for integer

I have made composite type named t_user_type:
CREATE TYPE t_user_type AS
(uid integer,
firstname character varying,
lastname character varying,
companyname character varying,
email character varying,
sip_phone integer);
...and I need to cast string to that type, so I do
SELECT '(11423, FirstName, LastName, Company, email#gmail.com, 204)' :: t_user_type;
everythin is fine. No errors, nothing. But when I do that same thing using procedure, I get this error: Invalid input syntax for integer: "(11423," FirstName"," LastName"," Company"," email#gmail.com", 204)".
Here is my procedure:
CREATE OR REPLACE FUNCTION change_type(p_user character varying)
RETURNS void AS
$BODY$DECLARE
v_user_type t_user_type;
BEGIN
SELECT p_user :: t_user_type INTO v_user_type;
END;$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION change_type(character varying)
OWNER TO postgres;
And here is query that uses the procedure:
SELECT change_type(
'(11423, FirstName, LastName, Company, email#gmail.com, 204)');
Can anybody tell me what am I doing wrong?
Not sure why that fails I made small change where I just cast the value into your local variable and it appears to work. But I don't know why yet. Is it legal to SELECT INTO a variable like you were doing(I think so I can do it with regular text string into a text variable)? I usually do it like my example below when it's just a variable with no source table.
CREATE TYPE t_user_type AS
(uid integer,
firstname character varying,
lastname character varying,
companyname character varying,
email character varying,
sip_phone integer);
SELECT '(11423, FirstName, LastName, Company, email#gmail.com, 204)' :: t_user_type;
CREATE OR REPLACE FUNCTION change_type(p_user character varying)
RETURNS t_user_type AS
$BODY$DECLARE
v_user_type t_user_type;
BEGIN
v_user_type := CAST(p_user AS t_user_type);
return v_user_type;
END;$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION change_type(character varying)
OWNER TO postgres;
SELECT change_type(
'(11423, FirstName, LastName, Company, email#gmail.com, 204)');