Error "relation does not exist" in PostgreSQL function() - sql

Function defined:
CREATE OR REPLACE FUNCTION len_chars(t_name VARCHAR, f_name VARCHAR) RETURNS BIGINT AS $$
BEGIN
SELECT sum(char_length(f_name)) FROM t_name;
END;
$$ LANGUAGE plpgsql;
Calling it from psql
SELECT len_chars('public.tag', 'name');
for table "tag" and column "name" returns Error:
psql: ERROR: relation "t_name" does not exist
LINE 1: SELECT sum(char_length(f_name)) FROM t_name
^
QUERY: SELECT sum(char_length(f_name)) FROM t_name
CONTEXT: PL/pgSQL function len_chars(character varying,character varying) line 1 at SQL statement
Is it possible to choice table name in postgresql functions?

You need dynamic SQL for that. And to safely construct a dynamic SQL string, the best way is to use the format() function using %I placeholders to properly deal with quoting identifiers if needed.
CREATE OR REPLACE FUNCTION len_chars(t_name VARCHAR, f_name VARCHAR)
RETURNS BIGINT AS $$
declare
l_result bigint;
BEGIN
execute format('SELECT sum(char_length(%I)) FROM %I', f_name, t_name)
into l_result;
return l_result;
END;
$$ LANGUAGE plpgsql;

Related

How do I return a table from a function with a bespoke column name?

This function works:
CREATE OR REPLACE FUNCTION public.a()
RETURNS TABLE(a text)
LANGUAGE plpgsql
AS $function$
BEGIN
return query execute
'select a from ztable';
END;
$function$;
But when I try to add some text to the column name:
CREATE OR REPLACE FUNCTION public.a(prefix text)
RETURNS TABLE(a text)
LANGUAGE plpgsql
AS $function$
BEGIN
return query execute
'select a as $1_a from ztable' using prefix;
END;
$function$;
This just fails as a syntax error on $1.
Or:
CREATE OR REPLACE FUNCTION public.a(prefix text)
RETURNS TABLE(a text)
LANGUAGE plpgsql
AS $function$
BEGIN
return query execute
'select a as '||prefix||'_a from ztable';
END;
$function$;
select * from a('some prefix') doesn't work.
Is there some other syntax that does the job?
That's simply not possible. SQL does not allow dynamic column names.
You must assign a column alias with the call. Like:
SELECT a AS prefix_a FROM public.a();
Or in a column definition list directly attached to the function:
SELECT * FROM public.a() AS f(prefix_a);
Or, while dealing with a single output column, even just:
SELECT * FROM public.a() AS prefix_a;
See:
RETURNING rows using unnest()?

How I can return the result of query in Postgres?

I have function in PostgreSQL, when I want to return the results I got error :
ERROR: query has no destination for result data
HINT: If you want to discard the results of a SELECT, use PERFORM instead.
Here is summary my function ( it's too long to copy/paste all of code here)
CREATE OR REPLACE FUNCTION "schema"."test"(IN Id int8,)
RETURNS TABLE("Id" uuid, "SiteId" uuid, "Domain" varchar,
"JumpCost" numeric, "CPMCost" numeric, "PaymentModel" int8, "ComputedEpm" numeric,
"ClickedCampaignId" int8, "MainRubricId" int8, "ShowSlider" bool,
"ShowGoods" bool, "ShowTeaser" bool, "BidLimitCoeff" numeric,
"RtbActiveSiteStatByBannerId" int8, "ShowType" int8, "MinAge" int8) AS
$BODY$
DECLARE
rtbCampaignEpmCoeff NUMERIC(18,6);
maxRubricShows int;
showsRubricAddedPerClick int;
siteLossLimitPerRubric NUMERIC(18,6);
rtbMinRubricVisitsToShow int;
showAdsToUsersWithoutInterests boolean;
BEGIN
......
DO
$do$
......
$do$;
PERFORM "Id", "SiteId", "Domain", "JumpCost", "CPMCost", "PaymentModel",
5 as ComputedEpm, "ClickedCampaignId", "MainRubricId", "ShowSlider",
"ShowGoods", "ShowTeaser", "BidLimitCoeff", "RtbActiveSiteStatByBannerId",
"ShowType", "MinAge"
FROM mytable
ORDER BY "FromClick" DESC, "Similarity" DESC, "rn", random()
LIMIT 1;
END;
$BODY$
LANGUAGE plpgsql
COST 100
CALLED ON NULL INPUT
SECURITY INVOKER
VOLATILE;
As you see I used "PERFORM" to return results, but failed with error I explained.
Also, I used "Return query .. " and got same error.
"mytable" is temp table that I created in function.
How I can return this result?
maybe something like this?
CREATE OR REPLACE FUNCTION my_function(user_id integer)
RETURNS TABLE(id integer, firstname character varying
, lastname character varying) AS
$$
DECLARE
ids character varying;
BEGIN
ids := '';
--Some code which build the ids string, not interesting for this issue
RETURN QUERY EXECUTE 'SELECT users.id, users.firstname, users.lastname
FROM public.users WHERE ids IN (' || ids || ')';
END;
$$ LANGUAGE plpgsql;

PostgreSQL: No function matches the given name and argument types

I have the following procedure:
DROP FUNCTION presAdress();
CREATE FUNCTION presadress() RETURNS VARCHAR(100) AS $$
DECLARE studioName text;
BEGIN
RETURN (
SELECT address AS pres_address
FROM MovieExec
WHERE cert# IN (
SELECT presC#
FROM Studio
WHERE name = studioName)
);
END;
$$ LANGUAGE plpgsql;
I try to run the procedure:
select presadress('Paramount');
But I get the following error message:
ERROR: function presadress(text) does not exist
SQL state: 42883
Hint: No function matches the given name and argument types. You might need to add explicit type casts.
Character: 294
I suspect that this is because there is some kind of error regarding the in parameters of the procedure, but I have been unable to find a solution.
Use a function parameter, like #Gordon demonstrates, but you don't need plpgsql for this at all. And the query can simplified (shorter, faster):
CREATE FUNCTION presadress(_studioname text)
RETURNS text AS
$$
SELECT m.address
FROM studio s
JOIN movieexec m ON m.cert# = s.presc#
WHERE s.name = _studioname
$$ LANGUAGE sql STABLE;
Function volatility can be STABLE.
Related:
How do IMMUTABLE, STABLE and VOLATILE keywords effect behaviour of function?
Difference between language sql and language plpgsql in PostgreSQL functions
PostgreSQL Stored Procedure Performance
I think you want a declaration more like this:
CREATE FUNCTION presadress (v_studioName text)
RETURNS VARCHAR(100) AS $$
BEGIN
RETURN(SELECT address AS pres_address
FROM MovieExec
WHERE cert# IN (SELECT presC#
FROM Studio
WHERE name = v_studioName)
);
END;
$$ LANGUAGE plpgsql;

Create function which return size of table

My code:
CREATE OR REPLACE FUNCTION sizeOfTableFunction
(
p_tableName varchar(100)
)
RETURNS integer
AS $$
DECLARE
p_tableSize integer;
BEGIN
SELECT count(*) into p_tableSize from p_tableName;
return p_tableSize;
END;
$$ LANGUAGE plpgsql STRICT;
Function has been created properly:
CREATE FUNCTION
Execute:
SELECT * FROM sizeOfTableFunction('Run');
Output - problem with executing the function?:
mydb=> SELECT * FROM sizeOfTableFunction('Run');
ERROR: relation "p_tablename" does not exist
LINE 1: SELECT count(*) from p_tableName
^
QUERY: SELECT count(*) from p_tableName
CONTEXT: PL/pgSQL function "sizeoftablefunction" line 5 at SQL statement
You need dynamic SQL for that:
CREATE OR REPLACE FUNCTION sizeOfTableFunction
(
p_tableName varchar(100)
)
RETURNS integer
AS $$
DECLARE
p_tableSize integer;
BEGIN
execute 'SELECT count(*) from '||p_tableName into p_tablesize; -- this is the difference
return p_tableSize;
END;
$$ LANGUAGE plpgsql STRICT;
To be safe, it's better to use the quote_ident function, just in case your tablename contains special characters. It also gives you some protection from SQL injection.
execute 'SELECT count(*) from '||quote_ident(p_tableName) into p_tablesize;

Function with SQL query has no destination for result data

I am trying to create a function that returns a SELECTed resultset.
When I call my postgres function like this select * from tst_dates_func() I get an error as shown below:
ERROR: query has no destination for result data
HINT: If you want to discard the results of a SELECT, use PERFORM instead.
CONTEXT: PL/pgSQL function "tst_dates_func" line 3 at SQL statement
********** Error **********
ERROR: query has no destination for result data
SQL state: 42601
Hint: If you want to discard the results of a SELECT, use PERFORM instead.
Context: PL/pgSQL function "tst_dates_func" line 3 at SQL statement
Here is the function I created:
CREATE OR REPLACE FUNCTION tst_dates_func()
RETURNS TABLE( date_value date, date_id int, date_desc varchar) as
$BODY$
BEGIN
select a.date_value, a.date_id, a.date_desc from dates_tbl a;
END;
$BODY$
LANGUAGE plpgsql;
I am not sure why I am getting the above error. I would like to run select * from tst_dates_func();
and get data back. Or further join the result set if needed. What is the problem here?
Do it as plain SQL
CREATE OR REPLACE FUNCTION tst_dates_func()
RETURNS TABLE( date_value date, date_id int, date_desc varchar) as
$BODY$
select a.date_value, a.date_id, a.date_desc from dates_tbl a;
$BODY$
LANGUAGE sql;
If you really need plpgsql use return query
CREATE OR REPLACE FUNCTION tst_dates_func()
RETURNS TABLE( date_value date, date_id int, date_desc varchar) as
$BODY$
BEGIN
perform SELECT dblink_connect('remote_db');
return query
select a.date_value, a.date_id, a.date_desc from dates_tbl a;
END;
$BODY$
LANGUAGE plpgsql;
In PLPGSQL - use RETURN QUERY
CREATE OR REPLACE FUNCTION tst_dates_func()
RETURNS TABLE( date_value date, date_id int, date_desc varchar) as
$BODY$
BEGIN
RETURN QUERY (select a.date_value, a.date_id, a.date_desc from dates_tbl a);
END;
$BODY$
LANGUAGE plpgsql;
I couldn't do it as plain SQL as I needed to enter some data into a database for further processing and wanted to create a variable. Or at least I did not figure out the correct syntax for that. And the accepted answer had code I did not need, such as connecting to the database, as I ran this from inside pgAdmin with a connection setup already. I also had to drop the function when I made edits to it.
I was using this for inserting a geometry for intersection. A different use case and example could help someone else. This also shows how to then view this data and use it just like a table.
-- Get a geojson shape inside of postgres for further use
DROP FUNCTION fun();
CREATE OR REPLACE FUNCTION fun()
RETURNS TABLE (geometry geometry) AS
$BODY$
DECLARE geojson TEXT;
BEGIN
geojson := '{
"type":"Polygon",
"coordinates":[[[-90.9516399548092,39.8942337977775],[-90.9513913202472,39.8936939306154],[-90.9522805177147,39.8937108246505],[-90.9549542293894,39.8937616571416],[-90.954948768846,39.8945506794343],[-90.9531755591848,39.894492766522],[-90.9531770788457,39.8942868819087],[-90.9516399548092,39.8942337977775]]],
"crs":{"type":"name","properties":{"name":"EPSG:4326"}},
}';
return query (SELECT ST_GeomFromGeoJSON(geojson) AS geometry);
END;
$BODY$
LANGUAGE plpgsql;
-- View test insert
SELECT * FROM fun()