PostgreSQL: Function does not exist - postgresql

Trying to create my first PostgreSQL function, I don't understand why I can't call this function.
CREATE FUNCTION public."SampledImpCountToOriginal"(IN integer)
RETURNS numeric
LANGUAGE 'plpgsql'
AS $BODY$
BEGIN
RETURN CASE WHEN $1 > 4 THEN EXP(POW($1 - 1.88, 1/2.3)) ELSE $1 END;
END;
$BODY$;
SELECT SampledImpCountToOriginal(5)
ERROR: function sampledimpcounttooriginal(integer) does not exist
LINE 1: SELECT SampledImpCountToOriginal(5)
^ HINT: No function matches the given name and argument types. You might need to add explicit type casts. SQL state:
42883 Character: 8
Calling from the same database I created it in, tried changing owner, can't figure it out. The function is listed in pgAdmin as SampledImpCountToOriginal(IN integer).

You have to call like this - SELECT "SampledImpCountToOriginal"(5)
When ever you use Double Quotes "" to create Function, you have to use in calling process. like -
SELECT public."SampledImpCountToOriginal"(
<integer>
)
If you don't use double quotes "" to calling your created function with "". it consider different function.
SELECT public.sampledimpcounttooriginal(
<integer>
)

Related

Facing issue while calling a stored procedure with if else condition in redshift

I created the stored procedure in redshift. Below is the code for that.
create or replace procedure sp4(f1 IN int)
as
$$
begin
IF f1==0 then
CREATE TABLE myetl(a int, b varchar);
ELSE
insert into new_tbl(id) values(47);
END IF;
end;
$$ LANGUAGE plpgsql;
While calling the stored procedure I am getting the error like this
call sp4(0)
ERROR: operator does not exist: integer == integer Hint: No operator matches the given name and argument type(s). You may need to add explicit type casts. Where: SQL statement "SELECT $1 ==0" PL/pgSQL function "sp4" line 2 at if
Your comparison should be IF f0 = 0 THEN, with single equal signs. See the Redshift PLpgSQL documentation

I have the following string '3,45,543,6,89'. Need output like table thorugh function. Pl help me get output through postgresql function

CREATE OR REPLACE FUNCTION public.SplitToTable(
iv_datalist varchar,iv_Separator varchar)
RETURNS TABLE(out_param varchar)
LANGUAGE 'plpgsql'
COST 100
VOLATILE
ROWS 1000
AS $BODY$
BEGIN
RETURN query select (select regexp_split_to_table(iv_datalist, iv_Separator) as out_param );
END
$BODY$;
When I run
select * from splitToTable('3,34,4,545,35,3',',');
I get this error:
ERROR: structure of query does not match function result type
DETAIL: Returned type text does not match expected type character varying in column 1.
CONTEXT: PL/pgSQL function splittotable1(character varying,character varying) line 4 at RETURN QUERY
SQL state: 42804
You'd have to declare the function as RETURNS text rather than RETURNS varchar. Use text everywhere, as that is the preferred string type in PostgreSQL. That way, you have no problems with type conversions.
The function could be written simpler as
CREATE OR REPLACE FUNCTION public.SplitToTable(
iv_datalist text,
iv_Separator text
) RETURNS TABLE(out_param text)
LANGUAGE sql
IMMUTABLE
AS
$BODY$SELECT * FROM regexp_split_to_table(iv_datalist, iv_Separator);$BODY$;
Essentially, the function is useless; you could just use regexp_split_to_table directly.

PostgreSQL PL/pgSQL syntax error with FOREACH loop

I'm trying to learn PL/pgSQL by writing some simple programs. To learn about FOREACH loop, I wrote the following:
CREATE OR REPLACE FUNCTION test(int[]) RETURNS void AS $$
DECLARE
window INT;
BEGIN
FOREACH window IN ARRAY $1
LOOP
EXECUTE 'SELECT $1' USING window;
END LOOP;
$$ LANGUAGE plpgsql;
SELECT test(ARRAY [30,60]);
I expect that this code snippet would first print 30 and then 60. However, I get the following error.
psql:loop.sql:11: ERROR: syntax error at end of input
LINE 7: EXECUTE 'SELECT $1' USING window;
^
psql:loop.sql:13: ERROR: function test(integer[]) does not exist
LINE 1: SELECT test(ARRAY [30,60]);
^
HINT: No function matches the given name and argument types. You might need
to add explicit type casts.
So the function definition has a syntax error, but I don't understand what the error is and how to fix it. I'd appreciate any help. Thanks!
Your function is declared as returns void so you can't return anything from it. If you want to return multiple values, you need to use returns setof integer
But it has more problems than that.
you should give your parameter a name (not an error, but good coding style)
to return a value from a function you need to use return. To return multiple values (because of returns setof) you need to use return next
there is no need for a dynamic SQL to return a value, you can return the variable directly.
Also not not an error, but: window is a keyword, I wouldn't use a variable with that name.
Applying all that, your function should look like this:
CREATE OR REPLACE FUNCTION test(p_input int[])
RETURNS setof integer
as
$$
DECLARE
l_value INT;
BEGIN
FOREACH l_value IN ARRAY p_input
LOOP
return next l_value;
END LOOP;
end;
$$
LANGUAGE plpgsql;
I am not sure if you are aware, but there is already a built-in function which achieves the same thing: unnest().

Postgres: ERROR: value too long for type character(4)

I'm new to Postgres and currently trying to write a function that takes in an integer and then calls another (definitely working) pre-written function with that input. If I call the pre-written function directly, e.g.:
select * from func(3456789);
I get the result I expect, with no errors. However, if I call it inside my function:
create or replace function my_func(_id integer)
returns setof Record
as $$
declare
rec Record;
begin
for rec in
select * from func(_id)
loop
return next rec;
end loop;
end;
$$ language plpgsql
;
where I call it with exactly the same parameter:
select * from my_func(3456789);
I get the following error:
ERROR: value too long for type character(4)
CONTEXT: PL/pgSQL function my_func(integer) line 5 at FOR over SELECT rows
Why are these two cases different, and how can I fix it?
EDIT:
func(_sid) returns this:
CREATE FUNCTION func(_sid integer) RETURNS SETOF Record
LANGUAGE plpgsql
AS $$ ...
and Record is defines like this:
create type Record as (code char(8), name char(4), num integer, work char(4));
Every line that is returned by your function func is mapped to a Record.
So the error you are getting says that one of the lines in the function result contains at column positions of name and/or work a value bigger than the one required by the columns (wich is 4).

how do I pass a user defined type variable to a function as a parameter?

I want to pass a user defined type parameter to a PLPGSQL function, but I am getting this error at runtime:
dev=# select process_shapes();
ERROR: invalid input syntax for integer: "(,,7)"
CONTEXT: PL/pgSQL function process_shapes() line 9 at SQL statement
dev=#
For some reason, the parameters are not passed correctly and I have no idea why it doesn't work.
My functions are:
CREATE OR REPLACE FUNCTION join_shapes(first_shape shape_t,second_shape shape_t,OUT new_shape shape_t)
AS $$
DECLARE
BEGIN -- simplified join_shape()s function
new_shape.num_lines:=first_shape.num_lines+second_shape.num_lines;
END;
$$ LANGUAGE PLPGSQL;
CREATE OR REPLACE FUNCTION process_shapes()
RETURNS void AS $$
DECLARE
rectangle shape_t;
triangle shape_t;
produced_shape shape_t;
BEGIN
rectangle.num_lines:=4;
triangle.num_lines:=3;
SELECT join_shapes(rectangle,triangle) INTO produced_shape;
RAISE NOTICE 'produced shape = %s',produced_shape;
END;
$$ LANGUAGE PLPGSQL;
Type definition:
CREATE TYPE shape_t AS (
shape_id integer,
shape_name varchar,
num_lines integer
);
Postgres version: 9.6.1
When the target of a SELECT ... INTO statement is of a composite type, it will assign each of the columns returned by the SELECT to a different field in the target.
However, SELECT join_shapes(rectangle,triangle) returns a single column of type shape_t, and it's trying to cram the whole thing into the first column of the target, i.e. produced_shape.shape_id (hence the error message about a failed integer conversion).
Instead, you need a SELECT statement which returns three columns. Just replace
SELECT join_shapes(rectangle,triangle)
with
SELECT * FROM join_shapes(rectangle,triangle)
Alternatively, you could use
produced_shape := (SELECT join_shapes(rectangle,triangle));
which performs a single assignment, rather than trying to assign the target fields individually.
For other people whom want to pass composite types to functions:
create type pref_public.create_test_row_input as (
name text
);
create or replace function pref_public.create_test_row(test_row pref_public.create_test_row_input) returns pref_public.test_rows as $$
insert into pref_public.test_rows (name)
values
(test_row.name)
returning *;
$$ language sql strict security definer;
grant execute on function pref_public.create_test_row to pref_user;
You'll need to use row()
select * from pref_public.create_test_row(row('new row'));
More info here