PostgreSQL 9.3: Update tables contained in a view - postgresql

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.

Related

How to insert declared type variable into table | Postgress

I have been working on creating a store procedure that will select data from a table, do some modification to that data, and then I need to insert that modified data into the same table. Take an example my table name is student. My procedure looks like below:
create or replace procedure student_create(p_code varchar)
language plpgsql
as $$
declare
v_student public.student;
begin
select * into v_student from student where code = p_code and is_latest_version is true;
raise notice 'Value: %', v_student;
v_student.id = uuid_generate_v4();
v_student.version_created_at = now();
v_student.version_updated_at = v_student.version_created_at;
raise notice 'Value: %', v_student;
INSERT INTO public.student VALUES(v_student);
end;$$
I am getting errors while calling this procedure:
ERROR: column "id" is of type uuid but expression is of type hotel
LINE 1: INSERT INTO public.hotel VALUES(v_hotel)
I know I can make insert statements like I can get each value from the variable and set it like
INSERT INTO public.student VALUES(v_student.id, v_student.code, v_student.name);
But I don't want to do that because it will become tightly coupled and later if I add another column into the table then I need to add that column into this procedure as well.
Does anyone have idea how can I insert the declared type variable directly into table.
There is no table type, there is only row composite type. Check manual 43.3.4. Row Types.
use row type.
create or replace procedure student_create(p_code text)
language plpgsql
as $$
declare
v_student public.student
begin
for v_student in select * from student where code = p_code and is_latest_version is true
loop
v_student.id = uuid_generate_v4();
v_student.version_created_at = now();
v_student.version_updated_at = v_student.version_created_at;
v_student.is_latest_version = true;
v_student.code = p_code;
INSERT INTO student VALUES(v_student.*);
end loop;
end;$$;
call it: call student_create('hello');
3. use update clause directly.
create or replace procedure student_create_1(p_code text)
language plpgsql as $$
BEGIN
with a as ( select uuid_generate_v4() as id ,
now() as version_created_at,
now() as version_updated_at,
p_code as "code" from student
where code = p_code and is_latest_version is true)
INSERT INTO student(id, version_created_at, version_updated_at, code)
select a.id, a.version_created_at,a.version_updated_at,a."code" from a;
end
$$;
call it: call student_create_1('hello');
fiddle code: here

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

Print prepared dynamic query with result set in Postgresql function using DBeaver

I have the function in which I have prepared dynamic query, which I want print in output window before executing it.
Note: In the following example I have just add simple select statement to understand the requirement.
Sample tables:
create table t1
(
col1 int,
col2 text
);
insert into t1 values(1,'Table T1');
insert into t1 values(2,'Table T1');
create table t2
(
col1 int,
col2 text
);
insert into t2 values(1,'Table T2');
insert into t2 values(2,'Table T2');
Function:
create or replace function fn_testing(tbl_Name text)
returns table(col1 int,col2 text) as
$$
begin
return query execute 'select col1,col2 from '||tbl_name||'';
end;
$$
language plpgsql;
Function call:
select * from fn_testing('t2');
I want to print following in message window with result set too in result window:
select col1,col2 from t1;
You can use RAISE NOTICE for messages.
CREATE OR REPLACE FUNCTION fn_testing
(_tbl_name name)
RETURNS TABLE
(col1 integer,
col2 text)
AS
$$
DECLARE
_query text;
BEGIN
_query := format('SELECT col1, col2 FROM %I;', _tbl_name);
RAISE NOTICE '%', _query;
RETURN QUERY EXECUTE _query;
END;
$$
LANGUAGE plpgsql;
Note: There's a special type, name, for identifiers. And to prevent SQL injection or errors you should make sure the dynamic identifiers are properly quoted. You can use format() with %I for that.

How to pass a table as argtype to postgres function?

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');

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.