I'm using Oracle 12c with many databases that come and go. I can run "select * from all_users" and get a list of all of my users databases. Now I can specify which user's table I want to query, but I'd really like to query them all. So something like "select * from all_users.client" to get all clients from all users. I know that won't work, and frankly, there may be no way to do what I want here, but if there is please point me in the right direction.
I created a SQL script that you can run to export all the information from all the tables (that you have access to). Using SQLcl, you can set sqlformat csv so that any select that you run returns the columns comma delimited. You can also modify the select statement that is gathering the table names to limit the tables that you want to return.
Also note that I ran into some tables that had characters in the table name that are not valid for a file name. For example, I have some tables that have $ in the table name, but that is not a valid character for a file name so if you run into that scenario you may want to add a correction for that.
set pagesize 0
set linesize 20000
set heading off
set feedback off
spool export_tables.sql
SELECT 'spool ' || owner || '.' || table_name || '.csv' || chr(10)
|| 'select * from ' || owner || '.' || table_name || ';' || chr(10)
|| 'spool off'
FROM all_tables
WHERE owner NOT IN ('SYS',
'SYSTEM',
'OUTLN',
'DBSFWUSER',
'AUDSYS',
'DBSNMP',
'APPQOSSYS',
'XDB',
'WMSYS',
'OJVMSYS',
'CTXSYS')
ORDER BY owner, table_name;
spool off;
set sqlformat csv
set heading on
#export_tables.sql
I think you want to get all the tables of the user:
select * from all_tables order by owner, table_name;
It returns the user-name and table names
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 query which gives me all numeric columns in my Postgres database:
SELECT table_schema, table_name, column_name
FROM information_schema.columns
WHERE table_schema in (
'datawarehouse_x',
'datawarehouse_y',
'datawarehouse_z',
'datawarehouse_w'
)
and udt_name not in
('date','timestamp','bool','varchar')
and column_name not like '%_id'
This gives me, what I need:
table_schema table_name column_name
schema_1 table_x column_z
schema_2 table_y column_w
I checked it and it's fine.
What I do now want to do is, to query all these columns for each table as a select sum(column) and then insert this schema_name, table_name, query_result and the current date into a log table on a daily basis.
Writing the results into a target table shouldn't be a big deal, but how in the world can I run queries according to the results of this query?
Thanks in advance.
EDIT: What I will write afterwards would be a procedure, which takes these schema/table/column as input, then queries the table and writes into the log-table. I just do not know the part in-between. This is kind of what I would be doing then, but I don't know yet which types I should use for schema, table and column.
create or replace function sandbox.daily_routine_metrics(schema_name regnamespace, table_name regclass, column_name varchar)
returns void
language plpgsql
as $$
BEGIN
EXECUTE
'INSERT INTO LOGGING.DAILY_ROUTINE_SIZE
SELECT
'|| QUOTE_LITERAL(schema_name) ||' schema_name,' ||
QUOTE_LITERAL(table_name) ||' table_name, ' ||
QUOTE_LITERAL(column_name) ||' column_name, ' ||
'current_timestamp, sum(' || QUOTE_LITERAL(column_name) || ')
FROM ' || QUOTE_LITERAL(schema_name) ||'.'|| QUOTE_LITERAL(table_name);
END;
$$;
The feature you need is known as "dynamic SQL". It's an RDBMS-specific implementation; the documents for Postgres are here.
Whilst it's possible to achieve what you want in dynamic SQL, you might find it easier to use a scripting language like Python or Ruby to achieve this. Dynamic SQL is hard to code and debug - you find yourself concatenating lots of hardcoded strings with results from SQL queries, printing them to the console to see if they work, and realizing all sorts of edge cases blow up.
I am trying to derive a table with counts from multiple tables. The tables are not on my schema. The table names on the schema that I am interested in all start with 'STAF_' and end with '_TS'. The criteria i am looking for is where SEP = 'MO'. So for example, the query in its base form is:
select area, count(SEP) areacount
from mous.STAF_0001_TS
where SEP = 'MO'
group by area;
I have about 1000 tables that i'd like to do this for.
Ultimatly, I'd like the output to be a table on my schema that looks like the following:
area| areacount
0001| 3
0002| 7
0003| 438
Thank you.
As a first step I'd write an SQL query that generates an SQL query:
SELECT 'SELECT area, count(*) FROM '||c.table_name||'UNION ALL' as run_me
FROM all_tables c
WHERE c.table_name LIKE 'STAF\_%\_MS' escape '\'
Running this will produce an output that is another SQL query. Copy the result text out of your results grid and paste it back into your query pane. Delete the final UNION ALL and run it
Once you dig how to write an SQL query that generate an SQL query, you can look at turning it into a view, or creating a dynamic query in a string.
Gotta say, this is a horrible way to store data; you'd be better off using ONE table with an extra column containing whatever is in xxx of STAF_xxx_MS right now
In Oracle 12c, you can embed a FUNCTION that will query the number of rows in any given table. Then you can use that function in your main query. Here is an example:
WITH FUNCTION cnt ( p_owner VARCHAR2, p_table_name VARCHAR2 ) RETURN NUMBER IS
l_cnt NUMBER;
BEGIN
EXECUTE IMMEDIATE 'SELECT count(*) INTO :cnt FROM ' || p_owner || '.' || p_table_name INTO l_cnt;
RETURN l_cnt;
EXCEPTION WHEN OTHERS THEN
RETURN NULL; -- This will happen for entries in ALL_TABLES that are not directly accessible (e.g., IOT overflow tables)
END cnt;
SELECT t.owner, t.table_name, cnt(t.owner, t.table_name)
FROM all_tables t
where t.table_Name like 'STAF\_%\_MS' escape '\';
I have Oracle database with many schemas. I'd like to find xyz string in all the tables in one specific schema. I've tried to do it as in accepted answer here (Search All Fields In All Tables For A Specific Value (Oracle)). Unfortunately, I get error:
3 ORA-00903: invalid table name
ORA-06512: at line 8 SQL.sql 30 2
where line 8 is
SELECT COUNT(*) FROM ' || t.owner || '.' || t.table_name ||
How can I do this full search? I've also tried other googled solutions but none of them worked for me.
Adapted from the other answer, run this query:
SELECT
'SELECT '''|| owner||table_name||column_name|| ''' as locn, COUNT(*) FROM "' || owner || '"."' || table_name ||'" WHERE "'||column_name||'" = ''[VALUE YOURE LOOKING FOR HERE]'' UNION ALL'
FROM
all_tab_columns
WHERE owner <> 'SYS' and data_type LIKE '%CHAR%'
Replace the [VALUE YOURE LOOKING FOR HERE] with the value you're looking for. Replace the square brackets too. Do not touch any apostrophes.
Then run the query, and it'll produce a huge number of sql statements. Copy them out of your query tool results grid, paste them into the query area panel, delete the last union all and then run them. And wait. For a very long time. Eventually it'll produce a list of every table and column name, together with the count of the number of times that value you're looking for appears in that column
You can adapt the original code to cope with tables (and schemas, and columns) created with case-sensitive or otherwise invalid object identifiers, by treating everything as a quoted identifier.
EXECUTE IMMEDIATE
'SELECT COUNT(*) FROM "' || t.owner || '"."' || t.table_name || '"' ||
' WHERE "'||t.column_name||'" = :1'
INTO match_count
USING '1/22/2008P09RR8';
but using whatever string you're actually looking for, of course.
In the dynamic SQL that generates, the owner, table name and column name are now all enclosed in double quotes - which is what #CaiusJard is doing, but this still executes separate queries inside an anonymous block.
Oracle: 11g
OS: Linux
I have this very tricky questions which I am trying to solve but not able to get definite answers...
I did search on google...etc but not luck with my requirement...
Schema statistics are not reliable so want to query dba_tables..
also don't want to create any procedures or functions under database.. just trying to achieve with simple SQL.
Q.
How to spool all table row count of a particular schema and also display table_name?
A.
I can display count easily in spool but not able to get table name beside count..
e.g.
Table_Name Count
tab1 200
tab2 500
tab3 300
with below I can get count but not able to figure out table_name display in result...
spool runme.sql
select 'select count(*) from '|| owner || '.' || table_name || ';'
from dba_tables
where owner = 'user1'
order by table_name;
spool off
You can use a function like this, but it will be very slow:
create or replace
function get_rows( p_tname in varchar2 ) return number
as
l_columnValue number default NULL;
begin
execute immediate
'select count(*)
from ' || p_tname INTO l_columnValue;
return l_columnValue;
end;
/
select user, table_name,
get_rows( user||'.'||table_name) cnt
from user_tables
/
Code taken from this answer on Tom Kyte's site:
http://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:1660875645686
Without a function call it is also possible:
select
table_name,
to_number(
extractvalue(
xmltype(
dbms_xmlgen.getxml('select count(*) c from '||table_name))
,'/ROWSET/ROW/C')) count
from user_tables;
From the tip here:
http://laurentschneider.com/wordpress/2007/04/how-do-i-store-the-counts-of-all-tables.html