I have a database with the column "endpointid" in a lot of tables. I am looking for a search function that would find every table containing a specific endpointid in order to write a query to delete that endpoint. I have tried a delete function to delete it from all tables but that is not working properly since a specific endpointid might not be in all tables. I know the following query gives all tables with the column name:
select table_name from all_tab_columns where lower(column_name) like lower('%endpointid%');
How can I extend that query to search for a specific record of endpointid?
Here is an example to delete rows with a specific endpointid value:
CREATE TABLE mytest (
endpointid NUMBER
);
INSERT INTO mytest VALUES ( 1 );
INSERT INTO mytest VALUES ( 2 );
DECLARE
ep NUMBER := 2;
BEGIN
FOR t_rec IN (
SELECT
table_name
FROM
all_tab_columns
WHERE
lower(column_name) LIKE lower('%endpointid%')
) LOOP
EXECUTE IMMEDIATE 'delete from '
|| t_rec.table_name
|| ' where endpointid = :1'
USING ep;
END LOOP;
END;
Note that if these tables have foreign key relationships, this may fail, as it does not take into account the ordering of the table references. If that is needed, then you would need to structure your metatada query to find those relationships.
Related
I am trying to loop through 5 tables all with a similar naming format. I am able to return the tables names by using the query
select table_name from all tables
where table_name like '
order by table_name
My intention is to insert the data from all the 5 tables into one table where a particular date condition is met. I know I can do this via union all but this makes my script very long as I have to paste the same script for 5 tables, I was wondering if there is a way to do without using union all but rather using dynamic sql? I am new to dynamic sql.
It might look like this:
begin
for cur_r in (select table_name
from all_tables
where table_name like 'ABC%'
)
loop
execute immediate
'insert into target_table (id, name, address) ' ||
'select id, name, address from ' || cur_r.table_name ||
' where date_column = ' || trunc(sysdate);
end loop;
end;
/
loop through all_tables, fetching only those you're interested in
compose insert statement, presuming that all tables (from previous step) share the same set of common columns
include where clause, if you want
I have a Database called Knowledge in postgres. It has multiple schemas and every schema has same number of tables, table has same columns as well.
Now I want to create a new schema called Aggregate, table called aggregate.table1 and put values from schema1.table1 and schema2.table1 in it.
I need to add another column in Aggregate.table1 which holds the value representing schema.
If any value in schema1.table1 is updated then aggregate.table1 should get the updated values.
Question,
Is it possible in Postgresql? if so please help me with this.
I need this aggregated table for further processing
You can try writing an anonymous code block to iterate over all schemas and tables, so that you can import your data into the aggregate schema. The following block search for all tables contained in the schemas s1 and s2, creates a corresponding table in the schema s_agg and finally copies its records.
DO $$
DECLARE row record;
BEGIN
FOR row IN SELECT * FROM pg_tables WHERE schemaname IN ('s1','s2') LOOP
EXECUTE 'CREATE TABLE IF NOT EXISTS s_agg.'||quote_ident(row.tablename)||
' AS TABLE ' || quote_ident(row.schemaname)||'.'|| quote_ident(row.tablename) ||
' WITH NO DATA;';
EXECUTE 'INSERT INTO s_agg.' || quote_ident(row.tablename)
|| ' SELECT * FROM '||quote_ident(row.schemaname)||'.'||quote_ident(row.tablename);
END LOOP;
END;
$$;
Demo
CREATE SCHEMA s1;
CREATE SCHEMA s2;
CREATE SCHEMA s_agg;
CREATE TABLE s1.t1 (id int);
INSERT INTO s1.t1 VALUES (1);
CREATE TABLE s2.t1 (id int);
INSERT INTO s2.t1 VALUES (42);
DO $$
DECLARE row record;
BEGIN
FOR row IN SELECT * FROM pg_tables WHERE schemaname IN ('s1','s2') LOOP
EXECUTE 'CREATE TABLE IF NOT EXISTS s_agg.'||quote_ident(row.tablename)||
' AS TABLE ' || quote_ident(row.schemaname)||'.'|| quote_ident(row.tablename) ||
' WITH NO DATA;';
EXECUTE 'INSERT INTO s_agg.' || quote_ident(row.tablename)
|| ' SELECT * FROM '||quote_ident(row.schemaname)||'.'||quote_ident(row.tablename);
END LOOP;
END;
$$;
-- contains values of t1 from s1 and s2
SELECT * FROM s_agg.t1;
id
----
1
42
Note: This code works with the assumption that the aggregate schema is either empty or it has empty tables, otherwise data will be duplicated. If you run this periodically and the size of your tables isn't too large, you can add a DROP TABLE before the CREATE TABLE statement. To make it work on every commit on all tables of all schemas you have to take a look at TRIGGERS or even logical replication.
I want to write a stored procedure that grabs all of the tables in a schema that have a column called "ID" , once I have those tables I want to output the counts of unique IDs within each table.
ex.
table1
table2
Output:
I have the latter portion implemented but the first part I'm having difficulties with. Here's my script so far:
create or replace PROCEDURE get_id_counts
IS
BEGIN
FOR table_n in (SELECT * FROM dba_tables) LOOP
EXECUTE IMMEDIATE 'SELECT ID, COUNT(*) FROM MySchema.' || table_n.table_name || ' GROUP BY ID';
END LOOP;
END;
/
execute get_id_counts;
Currently I receive the error : "%s: invalid identifier", I assume this is caused by the fact that not all of the tables in the schema have the column "ID"
Assuming that your database is Oracle
Use the dba_tab_columns to get only those which has ID column
So extend your query from
SELECT * FROM dba_tables
to
SELECT * FROM dba_tables where table_name in (select table_name from dba_tab_columns where column_name = 'ID');
I have a main table that has two columns with table names and id's. And I have those tables with table names in my DB.
For example, I find particular table name, selecting id. And then I want to populate table with that name with data. And I want to do that in one query. How I can do that?
The goal: to populate with data all tables at once, that has the names that similar with values in table name column from main table.
That is how I'm getting the list of tables. I should probably loop through it.
select tbl from asp_tbl where asp in (
select id from (
SELECT * FROM DIMENSION WHERE EXTERNALKEY LIKE 'W16%')
);
And then I will try to merge the data from other tables inside the table that needs to be populated:
MERGE INTO tbl d
USING
(SELECT ? nums, ? names from data_table) s
ON(d.product = s.product and d.ga = s.ga and d.metric_id = s.metric_id)
WHEN MATCHED THEN UPDATE SET d.names = s.names
WHEN NOT MATCHED THEN INSERT (nums, names)values(s.nums,s.names);
Did I provide enough info?
As I understand you need some stored procedure witch may fulfil a table with some test data. If so you may write something like:
create procedure fulfil_test_data (p_table_name varchar2) is
begin
for x IN (select tbl from asp_tbl where asp in (
SELECT table_id FROM DIMENSION WHERE EXTERNALKEY LIKE p_table_name )) loop
execute immediate 'insert into '|| x.tbl ||' (nums, names)
select level , chr(ascci(''A'') + mod(level,26)) from dual connect by level < 1001';
end loop;
end;
/
And call it
begin
fulfil_test_data('W16%');
end;
/
Hi everyone what I'm wondering if I can do is create a table that lists the record counts of other tables. It would get those table names from a table. So let's assume I have the table TABLE_LIST that looks like this
name
---------
sports_products <-- contains 10 records
house_products <-- contains 8 records
beauty_products <-- contains 15 records
I would like to write a statement that pulls the names from those tables to query them and coount the records and ultimately produce this table
name numRecords
------------------------------
sports_products 10
house_products 8
beauty_products 15
So I think I would need to do something like this pseudo code
select *
from foreach tableName in select name from table_list
select count(*) as numRecords
from tableName
loop
You can have a function that is doing this for you via dynamic sql.
However, make sure to declare it as authid current_user. You do not want anyone to gain some sort of privilege elevation by exploiting your function.
create or replace function SampleFunction
(
owner in VarChar
,tableName in VarChar
) return integer authid current_user is
result Integer;
begin
execute immediate 'select count(*) from "' || owner || '"."' || tableName || '"'
INTO result;
return result;
end;
One option is to simply keep your DB statistics updated, use dbms_stats package or EM, and then
select num_rows
from all_tables
where table_name in (select name from table_list);
I think Robert Giesecke solution will work fine.
A more exotic way of solving this is by using dbms_xmlgen.getxml.
See for example: Identify a table with maximum rows in Oracle