how to update all tables with a particular column name - sql

I am trying to update all tables starting with string like 'agg%' and column_name ='%userid%'...
But i dont see any such examples online even though i was able to find option to select all tables with a particular column name and table name I need to do the same to update those tables something like this :
update TABLE_NAME set COLUMN_NAME='rajeev' WHERE COLUMN_NAME LIKE '%userid%'
and TABLE_NAME LIKE 'agg%'
FROM INFORMATION_SCHEMA.COLUMNS;
Help would be appreciated.
Thanks.

To get the update query for your condition
select
'update '||c.table_name||' set '||c.COLUMN_NAME||' = ''rajeev'';'
as my_update_query
from
(select
table_name,COLUMN_NAME
from INFORMATION_SCHEMA.COLUMNS
where table_name LIKE 'agg%' and COLUMN_NAME LIKE '%userid%') c
To execute
do $$
declare
arow record;
begin
for arow in
select
'update '||c.table_name||' set '||c.COLUMN_NAME||' = ''rajeev'';'
as my_update_query
from
(select
table_name,COLUMN_NAME
from INFORMATION_SCHEMA.COLUMNS
where table_name LIKE 'agg%' and COLUMN_NAME LIKE '%userid%') c
loop
execute arow.my_update_query;
end loop;
end;
$$;

Related

dynamic SQL ERROR: column "age" does not exist

postgres 12
I am trying to loop through a table which has schema , table_names and columns
I want to do various things like finding nulls ,row count etc. I failed at the first hurdle trying to update the col records.
table i am using
CREATE TABLE test.table_study (
table_schema text,
table_name text,
column_name text,
records int,
No_Nulls int,
No_Blanks int,
per_pop int
);
I populate the table with some schema names ,tables and columns from information_schema.columns
insert into test.table_study select table_schema, table_name, column_name
from information_schema.columns
where table_schema like '%white'
order by table_schema, table_name, ordinal_position;
I want to populate the rest with a function
function :-
CREATE OR REPLACE PROCEDURE test.insert_data_population()
as $$
declare s record;
declare t record;
declare c record;
BEGIN
FOR s IN SELECT distinct table_schema FROM test.table_study
LOOP
FOR t IN SELECT distinct table_name FROM test.table_study where table_schema = s.table_schema
loop
FOR c IN SELECT column_name FROM test.table_study where table_name = t.table_name
LOOP
execute 'update test.table_study set records = (select count(*) from ' || s.table_schema || '.' || t.table_name || ') where table_study.table_name = '|| t.table_name ||';';
END LOOP;
END LOOP;
END LOOP;
END;
$$
LANGUAGE plpgsql;
I get this error SQL Error [42703]: ERROR: column "age" does not exist. the table age does exist.
when I take out the where clause
execute 'update referralunion.testinsert ti set records = (select count(*) from ' || s.table_schema || '.' || t.table_name || ') ;';
it works, I just cant figure out whats wrong?
Your procedure is structured entirely wrong. What it results in is an attempt to get every column name for every table name in every schema. I would guess results in your column does not exist error. Further is shows procedural thinking. SQL requires think in terms of sets. Below I use basically your query to demonstrate then a revised version which uses a single loop.
-- setup (dropping schema references)
create table table_study (
table_schema text,
table_name text,
column_name text,
records int,
no_nulls int,
no_blanks int,
per_pop int
);
insert into table_study(table_schema, table_name, column_name)
values ('s1','t1','age')
, ('s2','t1','xyz');
-- procedure replacing EXECUTE with Raise Notice.
create or replace procedure insert_data_population()
as $$
declare
s record;
t record;
c record;
line int = 0;
begin
for s in select distinct table_schema from table_study
loop
for t in select distinct table_name from table_study where table_schema = s.table_schema
loop
for c in select column_name from table_study where table_name = t.table_name
loop
line = line+1;
raise notice '%: update table_study set records = (select count(*) from %.% where table_study.table_name = %;'
, line, s.table_schema, t.table_name, c.column_name;
end loop;
end loop;
end loop;
end;
$$
language plpgsql;
Run procedure
do $$
begin
call insert_data_population();
end;
$$;
RESULTS
1: update table_study set records = (select count(*) from s2.t1 where table_study.table_name = age; 2: update table_study set records = (select count(*) from s2.t1 where table_study.table_name = xyz; 3: update table_study set records = (select count(*) from s1.t1 where table_study.table_name = age; 4: update table_study set records = (select count(*) from s1.t1 where table_study.table_name = xyz;
Notice lines 2 and 3. Each references a column name that does not exist in the table. This results from the FOR structure with the same table name in different schema.
Revision for Single Select statement with Single For loop.
create or replace
procedure insert_data_population()
language plpgsql
as $$
declare
s record;
line int = 0;
begin
for s in select distinct table_schema, table_name, column_name from table_study
loop
line = line+1;
raise notice '%: update table_study set records = (select count(*) from %.% where table_study.table_name = %;'
, line, s.table_schema, s.table_name, s.column_name;
end loop;
end;
$$;
do $$
begin
call insert_data_population();
end;
$$;
RESULTS
1: update table_study set records = (select count(*) from s2.t1 where table_study.table_name = xyz;
2: update table_study set records = (select count(*) from s1.t1 where table_study.table_name = age;
Note: In Postgres DECLARE begins a block. It is not necessary to declared each variable. I would actually consider it bad practice. In theory it could require an end for each declare as each could be considered a nested block. Fortunately Postgres does not require this.

In postgres/timescaledb, for all tables that match filter get all results with condition

I have a timescale db with multiple tables having the same structure.
I want to retrieve the recent row from each table where a value is true.
My logic is to
retrieve all the tablenames for the tables where this condition can be true
loop over list of tablenames and select the rows where the condition is met
I get an syntax error on the FOR loop but I expect that I do more things wrong.
Can someone suggest a solution please? Thank you in advance.
DECLARE
tablename text;
BEGIN
FOR tablename IN
SELECT table_name FROM information_schema.tables
WHERE table_name LIKE 'ohlc%'
LOOP
SELECT WHERE tablename.is_active is TRUE
ORDER BY time_stamp DESC
Limit 1
END LOOP;
END;
translate your problem
find table that have specific column name in schema.
How to find a table having a specific column in postgresql
first condition meet then loop. Function to loop through and select data from multiple tables
most tricky issue is quote_ident.
create or replace function test0()
returns table (_is_active boolean, id int) as
$$
declare tbl text;
begin
for tbl in
select quote_ident( table_name)
from information_schema.columns
where table_schema = 'public'
and table_name ilike 'ohlc%'
and column_name = 'is_active'
loop
return query EXECUTE
'select ' || quote_ident('is_active') || ' , ' || quote_ident('id') || ' from ' || tbl || ' where '|| quote_ident('is_active') ||' is true';
end loop;
end
$$ language plpgsql;

Display column based on certain condition

I want to display column based on certain condition, is it possible for that as i do this getting an error.
select (
select column_name
from all_tab_cols
where table_name='BED_2016_MAR_CIT4114A_FYP1_G_'
and column_name like '%na%'
)
from BED_2016_MAR_CIT4114A_FYP1_G_;
A SQL query must list the columns it is using explicitly. You can do what you want using dynamic SQL (execute immediate). For example:
declare
sql varchar2(4000);
cols varchar2(4000);
begin
select listagg(column_name, ',') within group (order by column_name)
into cols
from all_tab_cols
where table_name = 'BED_2016_MAR_CIT4114A_FYP1_G_' and column_name like '%na%' ;
sql := '
create table newtab as
select #cols
from BED_2016_MAR_CIT4114A_FYP1_G_';
sql := replace(sql, '#cols', cols);
execute immediate sql;
end;
select *
from newtab;
Looks like the problem is in the where condition:
where table_name='BED_2016_MAR_CIT4114A_FYP1_G_'
and column_name like '%na%'
Remove the condition for table_name. You are already selecting from BED_2016_MAR_CIT4114A_FYP1_G_ so only columns in that table will be shown.
Here is a more simplified version of the query:
select column_name
from BED_2016_MAR_CIT4114A_FYP1_G_
where column_name like '%na%'
Hope that helped

how to trim trailing spaces from every columns in all tables in PostgreSQL database

Am struggled in this task that is I need to trim all the trailing spaces from each and every columns of all tables in my PostgreSQL Database.
   
I've
update tbl_sale set product=trim(product) where product LIKE '% '
this will TRIM the product column in table tbl_sale.
In my database 137 tables are there,So is it possible to TRIM all the columns in my databases if a it have trailing space ?
Following query will return all tables and their columns that may or may not have trailing spaces.
NOTE : I'm assuming that all tables have tbl_ prefix.
select
table_name,COLUMN_NAME
from
INFORMATION_SCHEMA.COLUMNS
where
table_name LIKE 'tbl_%' and (data_type='text' or data_type='character varying')
to get the UPDATE query for all tables use the following select
select
'UPDATE '||quote_ident(c.table_name)||' SET '||c.COLUMN_NAME||'=TRIM('||quote_ident(c.COLUMN_NAME)||')
WHERE '||quote_ident(c.COLUMN_NAME)||' ILIKE ''% '' ' as script
from (
select
table_name,COLUMN_NAME
from
INFORMATION_SCHEMA.COLUMNS
where
table_name LIKE 'tbl_%' and (data_type='text' or data_type='character varying')
) c
This will return rows like update tbl_sale set product=trim(product) where product LIKE '% ' to update all columns in all tables.
Finally,
Use this method to update all columns in a database that having trailing space.
do $$
declare
selectrow record;
begin
for selectrow in
select
'UPDATE '||quote_ident(c.table_name)||' SET '||c.COLUMN_NAME||'=TRIM('||c.COLUMN_NAME||') WHERE '||quote_ident(c.COLUMN_NAME)||' ILIKE ''% '' ' as script
from (
select
table_name,COLUMN_NAME
from
INFORMATION_SCHEMA.COLUMNS
where
table_name LIKE 'tbl_%' and (data_type='text' or data_type='character varying' )
) c
loop
execute selectrow.script;
end loop;
end;
$$;
Wrap the above method into a Function, So that it is more convenient to use future
create function rm_trail_spaces() returns void as
$$
declare
selectrow record;
begin
for selectrow in
select
'UPDATE '||quote_ident(c.table_name)||' SET '||quote_ident(c.COLUMN_NAME)||'=TRIM('||quote_ident(c.COLUMN_NAME)||') WHERE '||quote_ident(c.COLUMN_NAME)||' ILIKE ''% '' ' as script
from (
select
table_name,COLUMN_NAME
from
INFORMATION_SCHEMA.COLUMNS
where
table_name LIKE 'tbl_%' and (data_type='text' or data_type='character varying' )
) c
loop
execute selectrow.script;
end loop;
end;
$$
language plpgsql
usage: SELECT rm_trail_spaces()
           

Checking for the existence of a column in a view before searching for a value

I am trying to search every view in the database for a specific value of something like '%THIS%'
I came up with this plsql code
DECLARE
match_count INTEGER;
BEGIN
FOR t IN (SELECT name FROM user_dependencies where type = 'VIEW') LOOP
EXECUTE IMMEDIATE
'SELECT COUNT(*) FROM '|| t.name || ' Where Column_Name LIKE ''%THIS%'' '
INTO match_count;
IF match_count > 0 THEN
dbms_output.put_line( t.name ||' '||match_count );
END IF;
END LOOP;
END;
But when I try to run it, I get an invalid identifier error for the column name in the execute immeadiate query.
The problem to me is obvious that not every view has the Column_Name, but I can't figure out how I can check to see if the column exists before running the query as I loop through all of the views.
I was also able to use a slightly modified version of this to run through all of the tables, and while they do not all have that column, I did not run in to this issue.
Edit: I am including the plsql code that I was able to use to loop through the tables.
DECLARE
match_count INTEGER;
BEGIN
FOR t IN (SELECT table_name, column_name FROM all_tab_columns
where table_name LIKE 'THIS%' and data_type = 'VARCHAR2' AND column_name = 'Column_name') LOOP
EXECUTE IMMEDIATE
'SELECT COUNT(*) FROM '||t.table_name || ' Where Column_name LIKE ''%THIS%'' '
INTO match_count;
IF match_count > 0 THEN
dbms_output.put_line( t.table_name ||' '||t.column_name||' '||match_count );
END IF;
END LOOP;
END;
I'm assuming this is Oracle since you tagged pl/sql. You can use Oracle's metadata tables to see what columns a table/view has. Specifically USER_TAB_COLUMNS.
select count(*)
from user_tab_columns
where table_name = [name of view]
and column_name = [name of column]
This should query every view that has a column_name like '%START%'
declare
cursor getViews is
select table_name, column_name from user_tab_cols where table_name in
(select view_name from user_views)
and column_name like '%START%';
myResult number;
BEGIN
for i in getViews
LOOP
execute immediate 'select count(*) from '||i.table_name into myResult;
END LOOP;
END;