PostgreSQL function does not return a value - postgresql

-- I can not understand where the error
CREATE OR REPLACE FUNCTION get_person_membership (IN person_urn CHARACTER VARYING)
RETURNS TEXT AS
$BODY$
DECLARE
result text;
urn ALIAS FOR $1;
BEGIN
SELECT INTO result pers.mx_groupmember FROM mt_person AS pers, mxt_recordheader AS rech
WHERE rech.primaryurn = 'urn'
AND rech.entitytype = 'person'
AND rech.logicalserverprefix = 'EA'
AND rech.id = pers.id;
RETURN result;
END;
$BODY$
LANGUAGE plpgsql
VOLATILE
COST 100

i simplified your query:
For input you can use $1, this goes to direct your condition.
You can return direct your result if you dont need anywhere else.
select * from get_person_membership('something');
CREATE OR REPLACE FUNCTION get_person_membership (IN person_urn CHARACTER VARYING)
RETURNS TEXT AS
$BODY$
BEGIN
RETURN (select pers.mx_groupmember --returns single value
FROM mt_person AS pers, mxt_recordheader AS rech
WHERE rech.primaryurn = $1 --input value from person_urn
AND rech.entitytype = 'person'
AND rech.logicalserverprefix = 'EA'
AND rech.id = pers.id);
END;
$BODY$
LANGUAGE plpgsql
VOLATILE
COST 100

No need for PL/pgSQL, a simple SQL function will do:
CREATE OR REPLACE FUNCTION get_person_membership (IN person_urn CHARACTER VARYING)
RETURNS TEXT AS
$BODY$
SELECT pers.mx_groupmember
FROM mt_person AS pers
JOIN mxt_recordheader AS rech ON rech.id = pers.id
WHERE rech.primaryurn = person_urn --<< input parameter
AND rech.entitytype = 'person'
AND rech.logicalserverprefix = 'EA';
$BODY$
LANGUAGE sql;

Related

postgresql plpgsql: not able to iterate over a array of varchar[] type

i am trying to check if a element is present in an array using plpgsql.
and i am receiving "array subscript must have integer" error while executing the function.
select test('IND') should return true and select test('ING') should return false
Below is the code
create or replace function test(country varchar)
returns varchar
language plpgsql
AS $function$
declare
results varchar;
countryarr varchar[3];
i varchar[];
begin
countryarr := array['IND','USA','MEX'];
foreach i slice 1 in array countryarr
loop
if countryarr[i]=country
then results := 'TRUE';
else
results := 'FALSE';
end if;
end loop;
return results;
end;
$function$
;
Your i is defined as a varchar[] in your code. It cannot be used as an integer.
You want something like this:
create or replace function test(country varchar)
returns varchar
language plpgsql
AS $function$
declare
countryarr varchar[3];
i text;
begin
countryarr := array['IND','USA','MEX'];
foreach i in array countryarr
loop
if i = country
then return 'TRUE';
end if;
end loop;
return 'FALSE';
end;
$function$
;
A better solution for what you are trying to achieve is:
create or replace function test(country varchar)
returns varchar
language sql
AS $function$
select case
when country = any(array['IND', 'USA', 'MEX']) then 'TRUE'
else 'FALSE'
end;
$function$;
Let your function return a boolean. Then it reduces to a single SQL statement.
create or replace function is_valid_country(country_in varchar)
returns boolean
language sql
immutable strict
AS $$
select country_in = any(array['IND', 'USA', 'MEX']) ;
$$;
with test(country) as
( values ('IND'), ('USA'), ('MEX'), ('CAN'),('UK') )
select country, is_valid_country(country) is_valid
from test;
This can be used in any subsequent sql statement. And the optimizer can in-line it.

Dynamically access RECORD value in pl/pgsql function

Why does accessing a value of the RECORD argument like this works:
CREATE OR REPLACE FUNCTION TT_GetVal1(a RECORD)
RETURNS text AS $$
DECLARE
BEGIN
RETURN a.val1::text;
END;
$$ LANGUAGE plpgsql VOLATILE;
SELECT TT_GetVal1(foo.*)
FROM (SELECT 1 id, 'a' val1) foo;
But not like this:
CREATE OR REPLACE FUNCTION TT_GetVal2(a RECORD)
RETURNS text AS $$
DECLARE
query text;
result text;
BEGIN
query = 'SELECT ($1).val1::text';
EXECUTE query INTO result USING a;
RETURN result;
END;
$$ LANGUAGE plpgsql VOLATILE;
SELECT TT_GetVal2(foo.*)
FROM (SELECT 1 id, 'a' val1) foo;
which returns:
ERROR: could not identify column "val1" in record data type
LINE 1: SELECT ($1).val1::text
How can I dynamically access RECORD values?
The RECORD only lives inside the plpgsql scope. The values are passed to the execute but not the column names.
You can - if the record is from a table - do something like this:
create table table1 (
id integer,
val1 text
);
CREATE OR REPLACE FUNCTION TT_GetVal2(a RECORD)
RETURNS text AS $$
DECLARE
query text;
result text;
BEGIN
query = 'SELECT ($1::text::table1).val1';
EXECUTE query INTO result USING a;
RETURN result;
END;
$$ LANGUAGE plpgsql VOLATILE;
SELECT TT_GetVal2(foo)
FROM (SELECT 1 id, 'a' val1) foo;
Best regards,
Bjarni

"query has no destination for result data" error even after having return in the function

Below is my function, even after having a RETURN statement, but a
query has no destination for result data
error is thrown. Am I missing something?
CREATE OR REPLACE FUNCTION test(ulds character varying)
RETURNS boolean AS
$BODY$
DECLARE
val_result boolean;
BEGIN
select * from regexp_split_to_array('BLK&AAK&AKE', '&');
SET val_result = false;
RETURN val_result;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION test(character varying)
There are more than one issues:
Result of unbind queries is not result of function in Postgres. You need to use INTO clause.
regexp_split_to_array is scalar function, there is not any reason to call this function from SELECT statement. Use SELECT only when you take result of table function, or when you need to read data from relations.
assign statement in plpgsql is based on := symbol. The command SET is used for something different.
the type text is proffered against varchar for function's parameters.
So your code can looks like:
CREATE OR REPLACE FUNCTION test(ulds text)
RETURNS boolean AS $$
DECLARE
result boolean;
target text[];
BEGIN
-- suboptimal, don't do this!!!
SELECT regexp_split_to_array('BLK&AAK&AKE', '&') INTO target;
-- preferred
target := regexp_split_to_array('BLK&AAK&AKE', '&');
result := true;
RETURN result;
END;
$$ LANGUAGE plpgsql;

In clause in postgres

Need Output from table with in clause in PostgreSQL
I tried to make loop or ids passed from my code. I did same to update the rows dynamically, but for select I m not getting values from DB
CREATE OR REPLACE FUNCTION dashboard.rspgetpendingdispatchbyaccountgroupidandbranchid(
IN accountgroupIdCol numeric(8,0),
IN branchidcol character varying
)
RETURNS void
AS
$$
DECLARE
ArrayText text[];
i int;
BEGIN
select string_to_array(branchidcol, ',') into ArrayText;
i := 1;
loop
if i > array_upper(ArrayText, 1) then
exit;
else
SELECT
pd.branchid,pd.totallr,pd.totalarticle,pd.totalweight,
pd.totalamount
FROM dashboard.pendingdispatch AS pd
WHERE
pd.accountgroupid = accountgroupIdCol AND pd.branchid IN(ArrayText[i]::numeric);
i := i + 1;
end if;
END LOOP;
END;
$$ LANGUAGE 'plpgsql' VOLATILE;
There is no need for a loop (or PL/pgSQL actually)
You can use the array directly in the query, e.g.:
where pd.branchid = any (string_to_array(branchidcol, ','));
But your function does not return anything, so obviously you won't get a result.
If you want to return the result of that SELECT query, you need to define the function as returns table (...) and then use return query - or even better make it a SQL function:
CREATE OR REPLACE FUNCTION dashboard.rspgetpendingdispatchbyaccountgroupidandbranchid(
IN accountgroupIdCol numeric(8,0),
IN branchidcol character varying )
RETURNS table(branchid integer, totallr integer, totalarticle integer, totalweight numeric, totalamount integer)
AS
$$
SELECT pd.branchid,pd.totallr,pd.totalarticle,pd.totalweight, pd.totalamount
FROM dashboard.pendingdispatch AS pd
WHERE pd.accountgroupid = accountgroupIdCol
AND pd.branchid = any (string_to_array(branchidcol, ',')::numeric[]);
$$
LANGUAGE sql
VOLATILE;
Note that I guessed the data types for the columns of the query based on their names. You have to adjust the line with returns table (...) to match the data types of the select columns.

PostgreSQL 9.3: isnumeric() in a condition

I need to check whether the given text is numeric or not from the
function.
Creating function for isnumeric():
CREATE OR REPLACE FUNCTION isnumeric(text) RETURNS BOOLEAN AS $$
DECLARE x NUMERIC;
BEGIN
x = $1::NUMERIC;
RETURN TRUE;
EXCEPTION WHEN others THEN
RETURN FALSE;
END;
$$ LANGUAGE plpgsql IMMUTABLE;
Function from which I am calling the isnumeric() function:
create or replace function tm(var text)
returns varchar as
$$
begin
if (select isnumeric(var))=t::BOOLEAN then
raise info 'Is numeric value';
else
raise info 'Not numeric';
end if;
end;
$$
language plpgsql;
Calling functon:
select tm('1');
Getting an error:
Here is the error details:
ERROR: column "t" does not exist
LINE 1: SELECT (select isnumeric(var))=t::BOOLEAN
You don't need a select (and it's actually wrong, as the error indicates) - just call isnumeric directly.
Also, by the way, your function is missing a return statement.
To sum it all up:
create or replace function tm(var text)
returns varchar as
$$
begin
if (isnumeric(var)) then -- call isnumeric directly
raise info 'Is numeric value';
else
raise info 'Not numeric';
end if;
return '0'; -- missing return value in the OP
end;
$$
language plpgsql;
this will help you to identify your field is numeric or not:
select * from Table where field_name ~ '^[0-9]*$'
for decimal values you can use^[0-9.]*$ instead ^[0-9]*$
select getDataType('2021'); == Number
select getDataType('2021-05-12 23:12:10'); == Date
select getDataType('2021-05-12'); == Date
select getDataType('2X'); == String
CREATE
OR REPLACE FUNCTION getDataType ( TEXT ) RETURNS TEXT AS $$ DECLARE
x VARCHAR;
BEGIN
x = $1 :: NUMERIC;
RETURN 'Number';
EXCEPTION
WHEN OTHERS THEN
BEGIN
x = $1 :: DATE;
RETURN 'Date';
EXCEPTION
WHEN OTHERS THEN
RETURN 'String';
END;
END;
$$ STRICT LANGUAGE plpgsql IMMUTABLE;