How to call Function within StoredProcedure in postgresql? - postgresql

I created one function
select * from f_get_employees1();
I want to call this function in stored procedure .

I don't know why you need to call a function into procedure.You don't need to do this. Even then I give some reference, so you can understand what you want.
CREATE OR REPLACE PROCEDURE dbo.spForCustomerINfo(
p_name character varying DEFAULT ''::character varying,
p_mobile character varying DEFAULT ''::character varying,
p_email character varying DEFAULT ''::character varying,
p_password character varying DEFAULT ''::character varying,
p_dob timestamp(3))
LANGUAGE 'plpgsql'
AS $BODY$
Declare p_CurrentAge varchar(20);
begin
-- Get User Current Age
Select dbo.fnGetCurrentAgeOfuser(p_dob) into p_CurrentAge;
----- Insert User Data
insert into dbo.Customer(name,mobile,email,password,DOB,CurrentAge)
values(p_name,p_mobile,p_email,p_password,p_dob,p_CurrentAge);
commit;
end;
$BODY$;

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$;

Not able to read values from xml in postgres

I am trying to read from a xml and insert them in a temporary table and return that table as a result. Below is the Postgres function I am trying with
CREATE OR REPLACE FUNCTION public.xml(
)
RETURNS TABLE(name character varying, description character varying, parentpid character varying, level integer, nodenumber character varying, displayorder integer, iscustom boolean)
LANGUAGE 'plpgsql'
COST 100
VOLATILE PARALLEL UNSAFE
ROWS 1000
AS $BODY$
declare
xmlvalue text := '<ArrayOfClientProcess>
<ClientProcess><Id>0</Id><IsActive>false</IsActive><LastModifiedBy>email</LastModifiedBy>
<LastModifiedOn>2022-04-27</LastModifiedOn><ClientId>0</ClientId><ProcessId>0</ProcessId>
<IsUserSelected>false</IsUserSelected><IndustryId>0</IndustryId><Occurrence>false</Occurrence><ParentPId>NULL</ParentPId>
<CAMSAssigned>false</CAMSAssigned><KPIAssigned>false</KPIAssigned><IsTechVariantAvailable>false</IsTechVariantAvailable>
<IBSCentralId>0</IBSCentralId><MasterId>0</MasterId><MasterCentralId>0</MasterCentralId><SegmentId>0</SegmentId><CAMId>0</CAMId>
<IsEPCAvailable>false</IsEPCAvailable><IsVariantAvailable>false</IsVariantAvailable><IsSubvariantAvailable>false</IsSubvariantAvailable>
<LOMVariantId>0</LOMVariantId><ProcessLevel>0</ProcessLevel><OperationsPresence>false</OperationsPresence><IsDigitalImpact>false</IsDigitalImpact>
<IsCrossIndustry>false</IsCrossIndustry><Name>FinanceCustom</Name><Description>Finance</Description><ParentId>0</ParentId><Level>0</Level>
<NodeNumber>0</NodeNumber><GeographyId>0</GeographyId><DisplayOrder>0</DisplayOrder><IsCustom>true</IsCustom><IsCustomMapped>false</IsCustomMapped>
<IsProcessChecked>false</IsProcessChecked><islinkedwithCPA>0</islinkedwithCPA><ProcessIdfromCPA>0</ProcessIdfromCPA>
<IsProcessCheckedOnLeftPane>false</IsProcessCheckedOnLeftPane></ClientProcess></ArrayOfClientProcess>';
begin
CREATE TEMPORARY TABLE tempClientProcess(name character varying,
description character varying,
parentpid character varying,
level integer,
nodenumber character varying,
displayorder integer,
iscustom boolean);
with data as (
select xmlvalue::xml val)
INSERT INTO tempClientProcess(name,description,parentpid,level,nodenumber,displayorder,iscustom)
SELECT d.name,d.description,d.parentpid,d.level,d.nodenumber,d.displayorder,d.iscustom
FROM data x,
XMLTABLE('/ArrayOfClientProcess/ClientProcess'
PASSING val
COLUMNS
name character varying PATH 'name',
description character varying PATH 'description',
parentpid character varying PATH 'parentpid',
level integer PATH 'level',
nodenumber character varying PATH 'nodenumber',
displayorder integer PATH 'displayorder',
iscustom boolean PATH 'iscustom') as d;
return query
select * from tempClientProcess ;
drop table tempClientProcess;
end;
$BODY$;
When i execute the function, the temporary table displays null as column values. Makes me think that it might not be able to read the values from xml properly. Something wrong I am doing while parsing maybe.
Assuming the invalid LastModifiedOn> is a copy & paste error, the error is in your XPATH expression for the columns. Tag names are case sensitive, so you need this column definition:
name character varying PATH 'Name',
description character varying PATH 'Description',
parentpid character varying PATH 'ParentPId',
level integer PATH 'Level',
nodenumber character varying PATH 'NodeNumber',
displayorder integer PATH 'DisplayOrder',
iscustom boolean PATH 'IsCustom'
Note that creating the temporary table in the function is completely unnecessary, you can return the result of xmltable() directly
CREATE OR REPLACE FUNCTION xml()
RETURNS TABLE(name character varying, description character varying, parentpid character varying, level integer, nodenumber character varying, displayorder integer, iscustom boolean)
LANGUAGE plpgsql
ROWS 1
AS $BODY$
declare
xmlvalue xml :=
'<ArrayOfClientProcess>
<ClientProcess><Id>0</Id><IsActive>false</IsActive><LastModifiedBy>email</LastModifiedBy>
<LastModifiedOn>2022-04-27</LastModifiedOn><ClientId>0</ClientId><ProcessId>0</ProcessId>
<IsUserSelected>false</IsUserSelected><IndustryId>0</IndustryId><Occurrence>false</Occurrence><ParentPId>NULL</ParentPId>
<CAMSAssigned>false</CAMSAssigned><KPIAssigned>false</KPIAssigned><IsTechVariantAvailable>false</IsTechVariantAvailable>
<IBSCentralId>0</IBSCentralId><MasterId>0</MasterId><MasterCentralId>0</MasterCentralId><SegmentId>0</SegmentId><CAMId>0</CAMId>
<IsEPCAvailable>false</IsEPCAvailable><IsVariantAvailable>false</IsVariantAvailable><IsSubvariantAvailable>false</IsSubvariantAvailable>
<LOMVariantId>0</LOMVariantId><ProcessLevel>0</ProcessLevel><OperationsPresence>false</OperationsPresence><IsDigitalImpact>false</IsDigitalImpact>
<IsCrossIndustry>false</IsCrossIndustry><Name>FinanceCustom</Name><Description>Finance</Description><ParentId>0</ParentId><Level>0</Level>
<NodeNumber>0</NodeNumber><GeographyId>0</GeographyId><DisplayOrder>0</DisplayOrder><IsCustom>true</IsCustom><IsCustomMapped>false</IsCustomMapped>
<IsProcessChecked>false</IsProcessChecked><islinkedwithCPA>0</islinkedwithCPA><ProcessIdfromCPA>0</ProcessIdfromCPA>
<IsProcessCheckedOnLeftPane>false</IsProcessCheckedOnLeftPane></ClientProcess>
</ArrayOfClientProcess>';
begin
return query
SELECT d.name,d.description,d.parentpid,d.level,d.nodenumber,d.displayorder,d.iscustom
FROM XMLTABLE('/ArrayOfClientProcess/ClientProcess'
PASSING xmlvalue
COLUMNS
name character varying PATH 'Name',
description character varying PATH 'Description',
parentpid character varying PATH 'ParentPId',
level integer PATH 'Level',
nodenumber character varying PATH 'NodeNumber',
displayorder integer PATH 'DisplayOrder',
iscustom boolean PATH 'IsCustom') as d;
end;
$BODY$;
In fact, you wouldn't even need PL/pgSQL for this. A simple language sql would do as well.

Syntax error at or near "IF" in PostgreSQL

I am trying to write an sql function on PostgreSQL, but I have an error with the 'IF':
ERROR: Syntax error at or near "IF"
LINE 11: IF Type = 's' THEN
I can't understand the syntax error.
(The Function without the IF work correctly)
My SQL Code:
CREATE OR REPLACE FUNCTION public.add_activity(IDactivity smallint,Date_Start date, Data_End date,
Type character varying,Name character varying DEFAULT NULL::character varying,
Typology character varying DEFAULT NULL::character varying, Client smallint DEFAULT NULL::smallint)
RETURNS void
LANGUAGE 'sql'
AS $BODY$
INSERT INTO public."Activity"
VALUES(IDactivity, Date_Start, Data_End, Type, Name);
IF Type = 's' THEN
INSERT INTO public."Service"
VALUES(IDactivity, Typology, Client);
END IF;
$BODY$;
Thank you!
IF is not implemented in the sql language but it is in the plpgsql language, see the manual.
You can either replace LANGUAGE sql by LANGUAGE plpgsql and then add BEGIN and END in the function body :
CREATE OR REPLACE FUNCTION public.add_activity(IDactivity smallint,Date_Start date, Data_End date,
Type character varying,Name character varying DEFAULT NULL::character varying,
Typology character varying DEFAULT NULL::character varying, Client smallint DEFAULT NULL::smallint)
RETURNS void
LANGUAGE plpgsql
AS $BODY$
BEGIN
INSERT INTO public."Activity"
VALUES(IDactivity, Date_Start, Data_End, Type, Name);
IF Type = 's' THEN
INSERT INTO public."Service"
VALUES(IDactivity, Typology, Client);
END IF;
END ;
$BODY$
Or you can change your code to stay in the sql language :
CREATE OR REPLACE FUNCTION public.add_activity(IDactivity smallint,Date_Start date, Data_End date,
Type character varying,Name character varying DEFAULT NULL::character varying,
Typology character varying DEFAULT NULL::character varying, Client smallint DEFAULT NULL::smallint)
RETURNS void
LANGUAGE sql
AS $BODY$
INSERT INTO public."Activity"
VALUES(IDactivity, Date_Start, Data_End, Type, Name);
INSERT INTO public."Service"
SELECT IDactivity, Typology, Client
WHERE Type = 's' ;
$BODY$

I am having a data insertion problem in tables "pm_feature_id" is primary key from table and it interlinked with other 2 tables

I am having a data insertion problem in tables "pm_feature_id" is primary key from table and it interlinked with other 2 tables.the primary key is auto increment and it declared as variable, i am inserting the data in tables by using below the code"
i am inserting the data but i am trying to return the data "pm_feature_name,pm_component_id" by using select statement
-- FUNCTION: project.fn_insert_features(character varying, integer, character varying, character varying, integer, integer)
-- DROP FUNCTION project.fn_insert_features(character varying, integer, character varying, character varying, integer, integer);
CREATE OR REPLACE FUNCTION project.fn_insert_features(
featurename character varying,
compntid integer,
descrptn character varying,
helpfilename character varying,
mediatypeid integer,
accntemplyid integer)
RETURNS TABLE(pm_feature_name character varying, pm_component_id integer)
LANGUAGE "sql"
COST 100
VOLATILE
ROWS 1000
AS $BODY$
DECLARE
v_id integer;
BEGIN
Insert into project.pm_features
(pm_feature_name,pm_component_id,pm_description)values (featurename,compntid,descrptn)
RETURNING pm_feature_id INTO v_id;
Insert into project.pm_help_files
(component_feature_id,help_file_name, media_type_id)values (v_id,helpfilename,mediatypeid);
Insert into project.pm_point_of_contacts
(component_feature_id,pm_account_employee_id)values(v_id,accntemplyid);
select pm_feature_name,pm_component_id from project.pm_features
END;
$BODY$;
ALTER FUNCTION project.fn_insert_features(character varying, integer, character varying, character varying, integer, integer)
OWNER TO pattesaadmin;
ERROR ERROR: syntax error at or near "integer" LINE 21: v_id integer;
^ SQL state: 42601 Character: 637
Try this out:
CREATE OR REPLACE FUNCTION project.fn_insert_features(
featurename character varying,
compntid integer,
descrptn character varying,
helpfilename character varying,
mediatypeid integer,
accntemplyid integer)
RETURNS TABLE(pm_feature_name character varying, pm_component_id integer)
LANGUAGE plpgsql
COST 100
VOLATILE
ROWS 1000
AS $BODY$
DECLARE
v_id integer;
BEGIN
Insert into project.pm_features
(pm_feature_name,pm_component_id,pm_description)values (featurename,compntid,descrptn)
RETURNING pm_feature_id INTO v_id;
Insert into project.pm_help_files
(component_feature_id,help_file_name, media_type_id)values (v_id,helpfilename,mediatypeid);
Insert into project.pm_point_of_contacts
(component_feature_id,pm_account_employee_id)values(v_id,accntemplyid);
return query select pm_features.pm_feature_name, pm_features.pm_component_id from project.pm_features;
END;
$BODY$;
ALTER FUNCTION project.fn_insert_features(character varying, integer, character varying, character varying, integer, integer)
OWNER TO pattesaadmin;
Note that I changed "sql" to plpgsql and added "return query" in front of the select statement and a semicolon at the end of the statement.
Hopefully this will be enough, I don't have the table descriptions to test completely.
Best regards,
Bjarni

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