How to pass a table as argtype to postgres function? - postgresql

create table test_tbl (id int, name character varying(10));
insert test_tbl values(1,'A');
insert test_tbl values(2,'B');
insert test_tbl values(3,'C');
insert test_tbl values(4,'D');
insert test_tbl values(5,'F');
Now i want to pass this table as a input argtype to function.
create function myfn (in tbl (how to define the table input))
as
return set of <some type>
begin
return query AS
select concat(id,name)
from test_tbl
where id in (select id from in_tbl);
end;
How to declare table type input argument?
How to call this function with table input?
select * from myfn(<pass the table - test_tbl>);

You can use the type regclass and build a dynamic query
create or replace function myfn (in tbl regclass)
returns TABLE(id INT)
as $$
begin
RETURN QUERY EXECUTE format('select id
from test
where id in (select id from %s)',tbl);
end
$$ LANGUAGE plpgsql;
and you call it using
select * from myfn('mytablename');

Related

how to get the result of the select query and pass it as a input to delete query in Function Postgresql

CREATE OR REPLACE FUNCTION test(name VARCHAR (255))
RETURNS INTEGER AS
$BODY$
DECLARE
emp_id INTEGER;
BEGIN
SELECT employee.employee_id into emp_id from employee where first_name = name;
DELETE FROM employee WHERE employee_id = emp_id;
return emp_id;
END
$BODY$
LANGUAGE plpgsql;
when i call the function its deleting all the records in my employee table.
First store value in a variable for given input and these execute delete command with this variable and return this variable.
-- PostgreSQL
-- create table and store data
create table employee (emp_id int, name varchar(255));
insert into employee values (1, 'Rahul'), (2, 'Biswas'), (3, 'Shuva');
-- create function
CREATE OR REPLACE FUNCTION test(p_name varchar(255))
RETURNS INTEGER AS
$BODY$
DECLARE v_emp_id INTEGER;
BEGIN
SELECT e.emp_id into v_emp_id from employee e where e.name = p_name;
DELETE FROM employee WHERE emp_id = v_emp_id;
return v_emp_id;
END
$BODY$
LANGUAGE plpgsql;
-- execute function
select * from test('Rahul');
Please check this url https://dbfiddle.uk/?rdbms=postgres_11&fiddle=4c134787dafd8fe58b032d700168318d

Select from a table, add a parameter to the result and return it from a function

I have a function that returns the result of a select based on a parameter being passed to it. I would like to join the parameter to the returned result of the function. Here's an example:
create or replace function somefunc(param varchar)
returns table(fielda varchar, fieldb int, param varchar)
language plpgsql
as $$
begin
return query
select
fielda varchar,
fieldb int,
param varchar -- HOW DO I SELECT IT?
from
sometable
join
othertable on id = other_id
end;
$$
You just need to call the parameter correctly
I created a fake sometable table and inserted two rows with
create table sometable(fielda varchar, fieldb int);
insert into sometable values('a',1);
insert into sometable values('b',2);
Then specified the somefunc function with
create or replace function somefunc(param_in varchar)
returns table(fielda varchar, fieldb int, param varchar)
language plpgsql
as $$
begin
return query
select
sometable.fielda,
sometable.fieldb,
param_in
from sometable;
end;
$$
Check out the param_in input parameter not in contrast with the param field in the table. I removed the join with the othertable but that can also be added.

How to write non parameterized function that returns table in postgresql

create or replace function demowhile_()
returns table (id integer,name varchar(50))
language 'plpgsql'
as $$
declare id integer;
declare name varchar(50);
begin
CREATE temporary TABLE demo_(id integer,name varchar(50));
CREATE temporary TABLE temp_ (id integer);
insert into temp_ (select id from demo);
while (select count(*) from temp_) <> 0
loop
id = (select top(1) id from temp_);
name = (select name from demo where id = id);
insert into demo_ values (id,name);
delete from temp_ where id = id;
end loop;
return query select id,name from demo;
end;
$$;
****while executing it is giving error like ****
select * from demowhile();
**ERROR: column reference "id" is ambiguous
LINE 1: insert into temp_ (select id,name from demo)
^
DETAIL: It could refer to either a PL/pgSQL variable or a table column.
QUERY: insert into temp_ (select id,name from demo)
CONTEXT: PL/pgSQL function demowhile() line 9 at SQL statement
SQL state: 42702**
demowhile_() returns table (id integer,name varchar(50) is basically the same thing as demowhile_(out id integer, out name varchar(50)) returns setof record
The id output column can be referenced directly from within the function. You've then also created a function variable named id. So when you assign a value to id, are you assigning to the output parameter or the declared variable? PG doesn't know, so you get that error.
And of course the simple solution is to give each a unique name.

plpgSQL return record type from FUNCTION

I'm trying to use a plgSQL witch return me a record type :
CREATE FUNCTION actu(id INTEGER) RETURNS RECORD AS $$
DECLARE
ret RECORD;
BEGIN
SELECT id_photo, id_user, lien, titre
FROM photo
WHERE id_user IN (
SELECT id_userabo
FROM abo
WHERE id_user = id )
ORDER BY date_publi DESC LIMIT 10;
RETURN ret;
END;$$
LANGUAGE plpgsql;
When I'm trying to use it with :
SELECT * FROM actu(4)
AS (id_photo Integer, id_photo Integer, lien Varchar, titre Varchar);
pgAdmin4 send me error :
ERROR: ERROR: the request has no destination for the resulting data
HINT: If you want to cancel the results of a SELECT, use PERFORM instead.
CONTEXT: PL/pgsql function fil_actu(integer), line 5 with SQL statement
The immediate error is, that the result of a select statement needs to be stored somewhere (that's what the error says). You would need to use select .. into ret from ... to store the result, but that wouldn't work as a variable of type record can only store one row from a result.
You apparently want to return more than just one row, so you need to define the function as returns table() and then use return query in PL/pgSQL to return the result of a query. But for a simple function encapsulating a SELECT query, a language sql function is more efficient.
CREATE FUNCTION actu(id INTEGER)
-- adjust the data types for the returned columns!
RETURNS table (id_photo int, id_user int, lien text, titre text)
AS $$
SELECT id_photo, id_user, lien, titre
FROM photo
WHERE id_user IN (SELECT id_userabo
FROM abo
WHERE id_user = id )
ORDER BY date_publi DESC
LIMIT 10;
$$
LANGUAGE sql;
You can use that function like this:
select *
from actu(42);
You may define those types inside the function, but with different names for the types. The return type can be a TABLE type and use RETURN QUERY to return the results.
CREATE FUNCTION actu(id INTEGER) RETURNS TABLE
(typ_id_photo Integer, typ_id_user Integer, typ_lien Varchar, typ_titre Varchar)
AS $$
BEGIN
RETURN QUERY
SELECT id_photo, id_user, lien, titre
FROM photo p
WHERE id_user IN (SELECT id_userabo
FROM abo
WHERE id_user = id )
ORDER BY date_publi DESC
LIMIT 10;
END;$$
LANGUAGE plpgsql;

PostgreSQL 9.3: Update tables contained in a view

I have a view which contains 3 tables. I want to update the each tables contained in the view.
Tables:
Table 1: test1
create table test1
(
id int,
name text,
city text
);
insert into test1 values(1,'Abc','xyz');
Table 2: test2
create table test2
(
id int,
name text,
city text
);
insert into test2 values(1,'bc','xz');
Table 3: test3
create table test3
(
id int,
name text,
city text
);
insert into test3 values(1,'Ac','yz');
View:
create view myview as select * from test1 union all select * from test2 union all select * from test3;
Note: I have a situation where I need to update the all tables city at once. So I have written a function
which does the update for a single table.
create or replace function updatefun(tablename text)
returns void as
$body$
Declare
query varchar;
Begin
query := 'Update '||tablename||'
set city = ''XXX''';
raise info '%',query;
execute query;
end;
$body$
Language plpgsql;
I have another table which contains the ViewId and ViewName.
create table viewdetails
(
ViewId int,
ViewName text
);
insert into viewdetails values(101,'myview');
Now I want to write another function to get all tables from the view and want to call the
function updatefun from this function to update all tables.
My try:
create or replace function fun1(vId int)
returns void as
$body$
declare
query varchar;
rec1 record;
rec2 record;
begin
DROP TABLE IF EXISTS temp_table1;
create temp table temp_table1(viewNames text);
query := 'insert into temp_table1 select ViewName from ViewDetails where ViewId = '|| vId ||'';
execute query;
for rec1 in select ViewNames from temp_table1 loop
for rec2 in SELECT Table_Name FROM INFORMATION_SCHEMA.VIEW_TABLE_USAGE WHERE View_Name = 'rec1' loop
select updatefun('rec2');
end loop;
end loop;
end;
$body$
language plpgsql;
Calling Function:
select fun1(101);
Checking view:
select * from myview;
Not getting why it is not getting updated??
This is incorrect:
select updatefun('rec2');
You want
perform updatefun(rec2);
without any quotes around rec2 otherwise it's interpreted as a literal, not the name of a variable.
Additionally rec2 should be of type TEXT, not RECORD.