How to use a function to get from tablename in postgresql? - database

thanks for help.
Sorry for bad english.
I created a function to return a tablename, for use in my select statement, here the script of function:
CREATE OR REPLACE FUNCTION getfromtable(objecttype varchar, destinationtable varchar, firstdate date, OUT tablename varchar)
AS $BODY$
declare
objectType ALIAS FOR $1;
destinationTable ALIAS FOR $2;
firstDate ALIAS FOR $3;
--tableResult varchar;
BEGIN
IF UPPER(objectType) = 'VIEW' THEN
select destinationTable || to_char(cast(firstDate as date),'yy') into tablename;
END IF;
IF UPPER(objectType) = 'TABLE' THEN
select destinationTable || to_char(cast(firstDate as date),'mmyy') into tablename;
END IF;
END;
$BODY$
LANGUAGE plpgsql
I need use this function, because i have table names with MMYY or views with YY in name ... the function works correctly, but, i need to use it in select, for example:
select * from getfromtable('TABLE','tab_venda_',current_date)
But, here is my problem, if i execute the script, the postgres return the table name, but not execute a select from a table ... i need execute a select in a table, not return the function...
How I wish it were
select * from tab_venda_0319
Whats i'm doing wrong?

You are not really doing something wrong, but functions just do not work that way. What the function returns is not a table name, but a value (parsing and query plan buildung are already done at that point).
Perhaps partitioning might help you?

Instead of returning the table name you can return the query result. See modified function.
CREATE OR REPLACE FUNCTION getfromtable(objecttype varchar, destinationtable varchar, firstdate date)
RETURNS SETOF RECORD
AS $BODY$
declare
objectType ALIAS FOR $1;
destinationTable ALIAS FOR $2;
firstDate ALIAS FOR $3;
tablename varchar;
BEGIN
IF UPPER(objectType) = 'VIEW' THEN
select destinationTable || to_char(cast(firstDate as date),'yy') into tablename;
END IF;
IF UPPER(objectType) = 'TABLE' THEN
select destinationTable || to_char(cast(firstDate as date),'mmyy') into tablename;
END IF;
RETURN QUERY EXECUTE 'SELECT * FROM '||tablename;
END;
$BODY$
LANGUAGE plpgsql;
While selecting you need to provide the column list for this to work as below
SELECT * FROM getfromtable('TABLE','tab_venda_',current_date) AS tab(column1_name column1_type, ...);

Related

issue when executing the pgsql complaining about loop

create or replace function f() RETURNS void AS
declare
tableArray text[] := '{"ADDRESS","CONSISTENCY_CHECK","DEPARTMENT_SUPERVISION"}';
tableName CHARACTER VARYING;
value INTEGER ;
BEGIN
FOREACH tableName IN ARRAY tableArray
LOOP
select user_id from tableName where user_id=2631;
if found then
update tableName set user_id=2651 where user_id=2631;
delete from tableName where user_id=2631;
END loop;
end;
here is the error that I get when trying to execute the pgplsql: ERROR syntax error at or near "loop"
There are more issues:
the body of function should be string - you can use apostrophes or more usual and practical $$ custom string separators.
the result of SELECT should not be lost. The clause INTO is missing.
table name should not be a variable - variable cannot be used as table name. In this case you need dynamic SQL - EXECUTE statement.
camel notation for variable names should not be used for SQL language, that is case insensitive
CREATE OR REPLACE FUNCTION f()
RETURNS void AS $$
DECLARE
table_array text[] := '{"ADDRESS","CONSISTENCY_CHECK","DEPARTMENT_SUPERVISION"}';
table_name text;
value integer ;
rc integer
BEGIN
FOREACH table_name IN ARRAY table_array
LOOP
EXECUTE format('SELECT * FROM %I WHERE user_id = $1', table_name) USING 2631;
-- variable FOUND cannot be used for dynamic SQL
GET DIAGNOSTICS rc = ROW_COUNT;
IF rc > 0 THEN
EXECUTE format('UPDATE %I SET user_id = $1 WHERE user_id = $2', table_name) USING 2651, 2631;
EXECUTE format('DELETE %I WHERE user_id = $1', table_name) USING 2631;
END IF;
END LOOP;
END;
$$ LANGUAGE plpgsql;

Return BIGINT[] FROM postgresql function

I know that some similar questions have been asked before but none of the answers worked for me!
I use POSTGRESQL 8.4 and am trying to return an array of BIGINT values from a function.
My query looks like:
CREATE OR REPLACE FUNCTION public.bigint_func(
in "in_arg" BIGINT)
RETURNS SETOF BIGINT
AS
$body$
DECLARE bigint_list BIGINT [ ];
BEGIN
SELECT
id
FROM
table1
INTO bigint_list;
RETURN NEXT;
END
$body$
LANGUAGE 'plpgsql'
VOLATILE
CALLED ON NULL INPUT
SECURITY INVOKER;
and I'd like to use that function as below:
SELECT *
FROM
table1
JOIN (SELECT ids
FROM bigint_func(123))t2 ON table1.id = t2.id
but I get the following error:
ERROR: query has no destination for result data
HINT: If you want to discard the results of a SELECT, use PERFORM instead.
How should I write the code for the function?
Looks like you might be blending two ways of doing what you are trying to accomplish. Either loop through and return a value at a time, or return everything as a query.
I think either of these will work.
Loop and return a row at a time.
CREATE OR REPLACE FUNCTION bigint_func(
in "in_arg" BIGINT)
RETURNS SETOF BIGINT
AS
$body$
DECLARE
bigint_list BIGINT [ ];
my_id bigint;
BEGIN
for my_id in
SELECT
id
FROM
table1
loop
RETURN NEXT my_id;
END loop;
end;
$body$
LANGUAGE 'plpgsql'
VOLATILE
Or return the entire query as a dataset.
CREATE OR REPLACE FUNCTION bigint_func(
in "in_arg" BIGINT)
RETURNS SETOF BIGINT
AS
$body$
DECLARE
bigint_list BIGINT [ ];
BEGIN
return query
SELECT
id
FROM
table1;
end;
$body$
LANGUAGE 'plpgsql'
VOLATILE
-- EDIT --
To get the query working, maybe change the return type to a table:
CREATE OR REPLACE FUNCTION bigint_func(in "in_arg" BIGINT)
RETURNS table (id bigint)
AS
$body$
BEGIN
return query
SELECT
table1.id
FROM
table1;
end;
$body$
LANGUAGE 'plpgsql'
VOLATILE;
Then you can name the field anything you want (id in this case)
SELECT *
FROM
table1
join bigint_func(123) t2
ON table1.id = t2.id

PostgreSQL - Array as function parameter

I want to know if it's posible to do something like this:
CREATE OR REPLACE function my_funct(some_data some_type, array int[])
RETURNS TABLE(code int, desc varchar)
LANGUAGE plpgsql
as $function$
DECLARE
..
BEGIN
WHILE some_condition < array.size --i know this doesn't exists
LOOP
INSERT INTO some_table values(array_data[1]); --I want to insert data from
the array as long as it has data
END LOOP;
RETURN QUERY select 1001, cast ('DONE!' as varchar);
END;
$function$
i would appreciate any response!
thanks!
A loop is typically not very efficient, use unnest() and insert the result in a single query:
CREATE OR REPLACE function my_funct(some_data some_type, array_data int[])
RETURNS TABLE(code int, descr varchar)
LANGUAGE plpgsql
as $function$
DECLARE
..
BEGIN
INSERT INTO some_table
select d.x
from unnest(array_data) as d(x);
RETURN QUERY select 1001, 'DONE!';
END;
$function$
You can however loop through an array as documented in the manual
BEGIN
FOREACH x IN ARRAY array_data
LOOP
INSERT INTO some_table values (x);
END LOOP;
RETURN QUERY select 1001, 'DONE!';
END;
That will be a lot slower though.

Use parameter as column name in table-valued function in SQL Server

ALTER FUNCTION [dbo].[cycleplan_doctor_view]
(#Parameter1 INTEGER, #Group VARCHAR(MAX))
RETURNS TABLE
AS
RETURN
(SELECT *
FROM tbl_master_doctor
WHERE int_doctor_id IN (SELECT int_doctor_id
FROM tbl_master_MR
WHERE int_user_id = #Parameter1
AND #Group = 'Yes')
)
When I am passing a value for #Group, I am getting empty table. But when I replace the value of #Group with its value it is working correctly.
I think I am missing some basic thing here.

Can a cursor hold variables in PL/pgSQL?

I know that a cursor can encapsulate a query, but can it also point to a variable value or multiple ones?
For example:
declare
my cursor refcursor;
var_x varchar;
begin
var_x := (select x from table where id = 7);
open mycursor for select(var_x);
end;
Is this possible in PL/pgSQL?
Yes, it can be done:
CREATE OR REPLACE FUNCTION f_value_cursor(_curs refcursor, _id1 int, _id2 int)
RETURNS TABLE (col1 int, col2 text) AS
$func$
DECLARE
var_x text := (SELECT t.col2 FROM tbl t WHERE t.tbl_id = _id1);
BEGIN
OPEN _curs FOR SELECT var_x;
RETURN QUERY
SELECT t.col1, t.col2
FROM tbl t
WHERE t.tbl_id >= _id2;
END
$func$ LANGUAGE plpgsql;
A cursor is good for any query that returns rows - even if it returns a single constant like in the example.
Using an unbound cursor variable as parameter, you can pass a name for the cursor to the function.
I made the function return a table at the same time, since that seems to be what you are after in those last couple of questions.
As mentioned in my previous answer, it is essential that you fetch values from the cursor in the same transaction:
BEGIN;
SELECT * FROM f_value_cursor('mycursor', 1, 2);
FETCH ALL FROM mycursor;
ROLLBACK; -- or COMMIT
SQL Fiddle.
For the record: consider a temporary table instead, which lives for the duration of the session (per default), not just for the transaction. Tables are much more versatile. Cursors make more sense for huge result sets.

Resources