splitting characters using function in PostgreSQL - postgresql

I tried to write function like this in PostgreSQL but I'm getting error like
ERROR: syntax error at or near "elems"
LINE 22: RETURN elems;
I want get output like
input: we###ty;rer##2hjjj
output:
we###ty
rer##2hjjj
please help me to solve this error
CREATE OR REPLACE FUNCTION public.fn_split(
inputstr text,
delimeter text)
RETURNS text[]
LANGUAGE 'plpgsql'
COST 100
VOLATILE SECURITY DEFINER PARALLEL UNSAFE
AS $BODY$
DECLARE
delimeter text;
elems text[];
var text;
arr_len int;
BEGIN
SELECT unnest(string_to_array(inputstr,delimeter))
INTO elems
RETURN elems;
END
$BODY$;

CREATE OR REPLACE FUNCTION public.fn_split(
inputstr text,
delimeter text)
RETURNS text[]
LANGUAGE 'plpgsql'
COST 100
VOLATILE SECURITY DEFINER
AS $BODY$
DECLARE
elems text[];
BEGIN
SELECT string_to_array(inputstr,delimeter) INTO elems;
RETURN elems;
END;
$BODY$;
Now call this function like this
SELECT UNNEST(fn_split('1,2,3',',')) as retval
Above is the screenshot which includes function definition and in the first list the command to call this function
Here is the command that you need to execute in order to call this function in the PostgreSQL query window after the creation of the function.

Your function is defined to return an array, however unnest would turn the result of creating the array into rows of strings. There is also no need to duplicate the parameter definition as local variables in a DECLARE block. And as you don't seem to want to manipulate the created array somehow, there is no need to store it in a local variable.
It seems you just want:
CREATE OR REPLACE FUNCTION public.fn_split(
inputstr text,
delimeter text)
RETURNS text[]
LANGUAGE plpgsql
immutable
AS $BODY$
BEGIN
return string_to_array(inputstr,delimeter);
END
$BODY$;
Or simpler as a SQL function:
CREATE OR REPLACE FUNCTION public.fn_split(
inputstr text,
delimeter text)
RETURNS text[]
LANGUAGE sql
immutable
AS
$BODY$
select string_to_array(inputstr,delimeter);
$BODY$;
Note that the language name is an identifier and should not be enclosed in single quotes. This syntax is deprecated and support for it will be removed in a future Postgres version.
Edit:
It seems you don't actually want an array, but one row per element after splitting the input value. In that case the function should be declared as returns table() not returns text[]
CREATE OR REPLACE FUNCTION public.fn_split(
inputstr text,
delimeter text)
RETURNS table(element text)
LANGUAGE sql
immutable
AS
$BODY$
select unnest(string_to_array(inputstr,delimeter));
$BODY$;
Then use it like this:
select *
from fn_split('we###ty;rer##2hjjj', ';');
Since Postgres 14
select unnest(string_to_array(inputstr,delimeter));
can be simplified to
select string_to_table(inputstr,delimeter);

Related

how to split string in PostgreSQL by making procedure

I tried split string like this but its not working.
If sneha####pai is the input, the output should be sneha pai
is this correct way to split string please help me.
CREATE OR REPLACE PROCEDURE public.splitstringcheck(
IN inputstr text)
LANGUAGE 'plpgsql'
SECURITY DEFINER
AS $BODY$
DECLARE
delimeter text;
elems text;
BEGIN
delimeter := '####';
elems := string_to_array(inputstr, delimeter);
END
$BODY$;
You used string_to_array function that is gonna return you an array, not splitted string in a way you want.
Result of the function string_to_array in your case is probably one dimensional array with two columns: {sneha,pai}. And its correct, but its not a function you should use here.
For this specific case you could use simpliest replace to achieve your goal.
For example:
select replace('sneha####pai','####',' ')
So your code could look like:
CREATE OR REPLACE PROCEDURE public.splitstringcheck(
IN inputstr text)
LANGUAGE 'plpgsql'
SECURITY DEFINER
AS $BODY$
DECLARE
delimeter text;
elems text;
BEGIN
delimeter := '####';
elems := replace(inputstr, delimeter,' ');
END
$BODY$;
What is more, remember that stored procedure cannot return value.
So either change stored procedure to function, or add an output parameter to the actual stored procedure.

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.

PostgreSQL - Function that returns labels of any ENUM

I am trying to write a "generic" function that will return labels of any enum (in any schema)...
But I am not having much luck because I am not sure what should argument type be...
The goal would be to be able to call function like this
SELECT common.get_enum_labels('public.rainbow_colors');
SELECT common.get_enum_labels('audit.user_actions');
This is what I have so
CREATE OR REPLACE FUNCTION common.get_enum_labels(enum_name regtype)
RETURNS SETOF text AS
$$
BEGIN
EXECUTE format('SELECT unnest(enum_range(NULL::%s))::text AS enum_labels ORDER BY 1', enum_name);
END;
$$
LANGUAGE plpgsql
STABLE
PARALLEL SAFE
;
Any tips would be appreciated
The argument type should be regtype, do not forget to return something from the function
CREATE OR REPLACE FUNCTION get_enum_labels(enum_name regtype)
RETURNS SETOF text AS
$$
BEGIN
RETURN QUERY
EXECUTE format('SELECT unnest(enum_range(NULL::%s))::text ORDER BY 1', enum_name);
END;
$$
LANGUAGE plpgsql
create or replace function get_enum_labels(enum_name regtype)
returns setof text language sql stable
as $$
select enumlabel::text
from pg_enum
where enumtypid = enum_name
order by enumsortorder
$$;

How to get the value of a dynamically generated field name in PL/pgSQL

Sample code trimmed down the the bare essentials to demonstrate question:
CREATE OR REPLACE FUNCTION mytest4() RETURNS TEXT AS $$
DECLARE
wc_row wc_files%ROWTYPE;
fieldName TEXT;
BEGIN
SELECT * INTO wc_row FROM wc_files WHERE "fileNumber" = 17117;
-- RETURN wc_row."fileTitle"; -- This works. I get the contents of the field.
fieldName := 'fileTitle';
-- RETURN format('wc_row.%I',fieldName); -- This returns 'wc_row."fileTitle"'
-- but I need the value of it instead.
RETURN EXECUTE format('wc_row.%I',fieldName); -- This gives a syntax error.
END;
$$ LANGUAGE plpgsql;
How can I get the value of a dynamically generated field name in this situation?
Use a trick with the function to_json(), which for a composite type returns a json object with column names as keys:
create or replace function mytest4()
returns text as $$
declare
wc_row wc_files;
fieldname text;
begin
select * into wc_row from wc_files where "filenumber" = 17117;
fieldname := 'filetitle';
return to_json(wc_row)->>fieldname;
end;
$$ language plpgsql;
You don't need tricks. EXECUTE does what you need, you were on the right track already. But RETURN EXECUTE ... is not legal syntax.
CREATE OR REPLACE FUNCTION mytest4(OUT my_col text) AS
$func$
DECLARE
field_name text := 'fileTitle';
BEGIN
EXECUTE format('SELECT %I FROM wc_files WHERE "fileNumber" = 17117', field_name)
INTO my_col; -- data type coerced to text automatically.
END
$func$ LANGUAGE plpgsql;
Since you only want to return a scalar value use EXECUTE .. INTO ... - optionally you can assign to the OUT parameter directly.
RETURN QUERY EXECUTE .. is for returning a set of values.
Use format() to conveniently escape identifiers and avoid SQL injection. Provide identifiers names case sensitive! filetitle is not the same as fileTitle in this context.
Are PostgreSQL column names case-sensitive?
Use an OUT parameter to simplify your code.

Hstore as argument type in postgresql

Is it possible to declare hstore as an argument type while creating a function in postgresql?
CREATE FUNCTION samplehstore(uname hstore)
RETURNS SETOF void AS
DECLARE
BEGIN
RAISE NOTICE 'uname : %', uname ;
END;
LANGUAGE plpgsql
Yes. Just tested:
create or replace function samplehstore(_h hstore)
returns text as
$$
begin
return _h->'a';
end
$$
language plpgsql;
select samplehstore('a=>1'::hstore)
>>> 1
Your example is ideally right, but you just forgot to surround the function body inside a string (the hstore part is ok). I recommend doing that this way (see $$ added):
CREATE FUNCTION samplehstore(uname hstore)
RETURNS SETOF void AS $$
DECLARE
BEGIN
RAISE NOTICE 'uname : %', uname ;
END;
$$
LANGUAGE plpgsql;
The PostgreSQL's functions are basically an string, and dollar-quoting is an syntax similar to single quotes, try this:
SELECT $$my string$$, $id$my string$id$, 'my string';
The three are equivalents. See the docs for more information.