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.
Related
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 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$;
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
How can I solve it use mybatis to return a table or setof from procedure call with postgresql. thanks
psotgreaql:
CREATE OR REPLACE FUNCTION public.p_find_battery_detail(
item character varying,
vaulestr character varying,
islimit boolean)
RETURNS TABLE(
id bigint,
no character varying,
chassis character varying,
channel character varying,
module character varying,
isformat bit,
isgrad bit,
ismatch bit,
ismastop bit,
sfile json,
sftimesign character varying,
groupclass character varying,
gradtimesign character varying,
gradf json)
LANGUAGE plpgsql
mybatis in java wiht annotation
#Select("call p_find_battery_detail(#{0}, #{1}, #{2})")
#Options(statementType = StatementType.CALLABLE)
List<BatteryInfoDetail> findBatteryDetail(String itemStr, String valueStr, boolean isLimit);
when i run this serch, will throw some error:
org.apache.ibatis.binding.BindingException: Parameter '0' not found. Available parameters are [arg2, arg1, arg0, param3, param1, param2]
and so on....
the shortest way to go forward is to apply the hint provided by error message:
#Select("call p_find_battery_detail(#{arg0}, #{arg1}, #{arg2})")
to go farther you name parameters by annotation to reuse this name in query:
#Select("call p_find_battery_detail(#{itemStr}, #{valueStr}, #{isLimit})")
#Options(statementType = StatementType.CALLABLE)
List<BatteryInfoDetail> findBatteryDetail(#Param("itemStr") String itemStr, Param("valueStr") String valueStr, Param("isLimit") boolean isLimit);
params may have any name you want.
#Select("select * from p_find_battery_detail(#{itemStr}, #{valueStr}, #{isLimit})")
List<BatteryDetail> findAll(#Param("itemStr") String itemStr, #Param("valueStr") String valueStr, #Param("isLimit") boolean isLimit);
I have function like this :
CREATE OR REPLACE FUNCTION f_insert_account(usernames character varying, passwds
character varying, identitass integer, jeniss smallint, statuss smallint, cnames
character varying, unames character varying)
RETURNS character varying AS
$BODY$
DECLARE
iduserx int4;
usernamex varchar;
er int2:=0;
pesan varchar:='';
BEGIN
insert into t_account(username,passwd,identitas,jenis,status,cname,uname)
values(usernamex,f_encr(passwds),identitass,jeniss,statuss,cnames,unames);
RETURN pesan;
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE;
ALTER FUNCTION f_insert_account(usernames character varying, passwds character
varying, identitass integer, jeniss smallint, statuss smallint, cnames character
varying, unames character varying) OWNER TO postgres;
GRANT EXECUTE ON FUNCTION f_insert_account(usernames character varying, passwds
character varying, identitass integer, jeniss smallint, statuss smallint, cnames
character varying, unames character varying) TO public;
GRANT EXECUTE ON FUNCTION f_insert_account(usernames character varying, passwds
character varying, identitass integer, jeniss smallint, statuss smallint, cnames
character varying, unames character varying) TO postgres;
then I use that like this :
select f_insert_account('dayat', 'dayat', 1, 1, 1, 'cname', 'uname')
Error like this always appear :
ERROR: function f_insert_account("unknown", "unknown", integer, integer, integer, "unknown", "unknown") does not exist
SQL state: 42883
Hint: No function matches the given name and argument types. You may need to add explicit type casts.
Character: 8
why is that ???
thanx,
Dayat
The smallint datatype is a bit of a gotcha, since you need to cast these:
select f_insert_account('dayat', 'dayat', 1, 1::smallint, 1::smallint, 'cname', 'uname')
If you want to avoid this, I suggest changing your function definition to use plain old integer types.