How to make a string from Array in plpgsql - postgresql

I've got a result from my function
EXECUTE format('SELECT ARRAY (SELECT tvmid from "%s".tvmtable order by tvmid)', operatorName) INTO tvms;
that gives mi array of tvms in format {1,2,3}. I need it to have a String divided with , so I'm trying like
SELECT ARRAY_TO_STRING(tvms, ",") INTO res;
but when I'm executing my function I got error
ERROR: column "," does not exist
If it helps here is my whole function
create or replace function getTVMList(operatorName varchar)
returns varchar as $$
declare
tvms varchar[];
res varchar;
begin
EXECUTE format('SELECT ARRAY (SELECT tvmid from "%s".tvmtable order by tvmid)', operatorName) INTO tvms;
SELECT ARRAY_TO_STRING(tvms, ",") INTO res;
return res;
end;
$$
language plpgsql;

Double quotes reference a column name.
You have to put the comma into single quotes instead of double quotes: ','
SELECT ARRAY_TO_STRING(tvms, ',') INTO res;

Related

How to nest variable in query string passed to function

I need to be able to get the value stored inside rec_key.empname when I call this function:
CREATE OR REPLACE FUNCTION public.txt(text)
RETURNS SETOF record
LANGUAGE plpgsql
AS $function$
declare
var_param text;
var_req TEXT;
rec_key record;
cur_key CURSOR FOR Select empname::varchar from employee;
BEGIN
open cur_key;
loop
fetch cur_key into rec_key;
EXIT WHEN NOT FOUND;
var_req :=
'
' || $1 || '
';
return query execute var_req;
end loop;
close cur_key;
END
$function$
;
What do I have to change to get the desired empname when calling the function?
If I call it like this it doesn't work: :(
select * from public.txt('select empid, age::integer,''''''|rec_key.empname|''''''::varchar from employee') as (empid integer, age integer, empname varchar)
To address the question asked:
CREATE OR REPLACE FUNCTION public.txt(_sql text)
RETURNS SETOF record
LANGUAGE plpgsql AS
$func$
DECLARE
_rec record;
BEGIN
FOR _rec IN
SELECT empname::text FROM employee
LOOP
RETURN QUERY EXECUTE _sql
USING _rec.empname;
END LOOP;
END
$func$;
Call:
SELECT * FROM public.txt('SELECT empid, age::integer, $1 AS empname FROM employee')
AS (empid integer, age integer, empname varchar);
The example does not make any sense, though, and all of it could be replaced with a simple query. See my anser to your earlier question:
Doesn't find variable when passing query as parameter
Use the much simpler implicit cursor of a FOR loop. See:
Cursor based records in PostgreSQL
Truncating all tables in a Postgres database
Pass the variable as value with a USING clause. $1 is the symbol to reference the first USING argument. See:
Replace double quotes with single quotes in Postgres (plpgsql)

Execute decode function stored in bytea column

I have a bytea column in a table that contains a function decode(). What I have done to get the actual data is as follows:
select filename, convert_from(data,'UTF-8') from attachments limit 20; //this returns me decode function
select decode(E'...','hex'); // I am executing the above returned function
The above is fine as long as I have to select one row. But now my requirement is to get more than one result. How can I get the result in single query? I have tried using pl/pgsql
CREATE OR REPLACE FUNCTION get_data(integer, _type anyelement, OUT _result anyelement)
AS
$x$
BEGIN
EXECUTE
'SELECT ' || (select convert_from(data,'UTF-8') as data from attachments limit $1)
INTO _result;
END;
$x$
LANGUAGE plpgsql;
But this works only for single row and single column. What I want is a single query to fetch 2 columns without using pl/pgsql if possible. I am using this query from my Java based web app.
Thanks!
You need procedural code for this, since there is no provision for dynamic statements in SQL.
The following function converts all attachments:
CREATE FUNCTION getemall(
IN v_type anyelement,
OUT v_result anyelement
) RETURNS SETOF anyelement
LANGUAGE plpgsql AS
$$DECLARE
v_stmt text;
BEGIN
FOR v_stmt IN
SELECT convert_from(data,'UTF-8')
FROM attachments
LOOP
EXECUTE v_stmt INTO v_result;
RETURN NEXT;
END LOOP;
END;$$;
This is how I have written the function with few changes
CREATE OR REPLACE FUNCTION getmeall(tName text, fNameCol text, dataCol text,fSize
numeric)
RETURNS TABLE(bdata bytea, fname text) LANGUAGE plpgsql AS
$$DECLARE
v_stmt text;
v_name text;
BEGIN
FOR v_stmt,v_name IN
EXECUTE format('SELECT encode(%s, ''escape''), %s FROM %s
WHERE $1 IS NOT NULL AND $2 IS NOT NULL LIMIT $3'
, dataCol, fNameCol, tName)
USING dataCol, fNameCol, fSize
LOOP
fname:=v_name;
IF strpos(v_stmt,'decode') = 1 THEN
EXECUTE 'SELECT ' || v_stmt INTO bdata;
ELSE
bdata:=v_stmt;
END IF;
RETURN NEXT;
END LOOP;
END;$$;
And finally calling it this way.
select * from getmeall('attachments', '"filename"', '"data"',2)

How to concat two string in postgresql function?

I want a function which will return concated string. I am getting following error after execute this function in postgresql.
CREATE OR REPLACE FUNCTION getTableName ()
RETURNS text AS $$
DECLARE
state_short_name text;
BEGIN
state_short_name := (select lower(state_short_name) from mst_state where state_code in (SELECT substr(entity_code,1,2) FROM shg_detail_share WHERE entity_code = '3420006002001'))
RETURN (CONCAT(state_short_name, '_shg_detail'));
END;
$$ LANGUAGE plpgsql
I expect the output like 'jh_shg_detail' but I am getting error like this
ERROR: syntax error at or near "("
LINE 9: RETURN (CONCAT(state_short_name, '_shg_detail'));
You should use a select into in PL/pgSQL. And to avoid a name clash, don't name variables the same as columns:
CREATE OR REPLACE FUNCTION gettablename()
RETURNS text AS $$
DECLARE
l_state_short_name text;
BEGIN
select lower(state_short_name)
into l_state_short_name
from mst_state
where state_code in (SELECT substr(entity_code,1,2)
FROM shg_detail_share
WHERE entity_code = '3420006002001'));
RETURN CONCAT(state_short_name, '_shg_detail');
END;
$$ LANGUAGE plpgsql;
But you don't need PL/pgSQL for a simple SQL query like that. Your sub-query isn't really necessary as well. You can simplify that to where state_code = '34'
CREATE OR REPLACE FUNCTION gettablename()
RETURNS text
AS $$
select concat(lower(state_short_name), '_shg_detail')
from mst_state
where state_code = '34';
$$
LANGUAGE sql;
Your problem is a missing semicolon at the line with the assignment statement :=.
This makes the line that starts with RETURN (CONCAT a continuation line of the statement, and so you get the syntax error reported in that line.

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.

I am trying to unnet an array in other to query the postgres DB

I am call the function but it is returning error that array value must start with "{" or dimension information using
Create or Replace Function get_post_process_info(IN v_esdt_pp character varying[])
Returns setof Record as
$$
Declare
post_processes RECORD;
esdt_value character varying;
v_sdsname character varying[];
v_dimension character varying[];
counter int := 1;
Begin
-- to loop through the array and get the values for the esdt_values
FOR esdt_value IN select * from unnest(v_esdt_pp)
LOOP
-- esdt_values as a key for the multi-dimensional arrays and also as the where clause value
SELECT distinct on ("SdsName") "SdsName" into v_sdsname from "Collection_ESDT_SDS_Def" where "ESDT" = esdt_values;
raise notice'esdt_value: %',esdt_value;
END LOOP;
Return ;
End
$$ Language plpgsql;
Select get_post_process_info(array['ab','bc]);
Your function sanitized:
CREATE OR REPLACE FUNCTION get_post_process_info(v_esdt_pp text[])
RETURNS SETOF record AS
$func$
DECLARE
esdt_value text;
v_sdsname text[];
v_dimension text[];
counter int := 1;
BEGIN
FOR esdt_value IN
SELECT * FROM unnest(v_esdt_pp) t
LOOP
SELECT distinct "SdsName" INTO v_sdsname
FROM "Collection_ESDT_SDS_Def"
WHERE "ESDT" = esdt_value;
RAISE NOTICE 'esdt_value: %', esdt_value;
END LOOP;
END
$func$ Language plpgsql;
Call:
Select get_post_process_info('{ab,bc}'::text[]);
DISTINCT instead of DISTINCT ON, missing table alias, formatting, some cruft, ...
Finally the immediate cause of the error: a missing quote in the call.
The whole shebang can possibly be replaced with a single SQL statement.
But, obviously, your function is incomplete. Nothing is returned yet. Information is missing.