Reputation: 132
Database - Oracle Database 10g Release 10.2.0.4.0 , working with Oracle SQL Developer
EDIT Sorry: Query-1 Should be :
SELECT TABLE_NAME FROM USER_TABLES;
earlier it was SELECT OWNER, TABLE_NAME FROM ALL_TABLES;
Output-1: ALL TABLES that I own
Query-2:
SELECT COUNT(*) FROM MYTABLE_1;
Output-2: Total number of rows in specific table MYTABLE_1
Query-3: SELECT MAX(ORA_ROWSCN) FROM MYTABLE_1;
Output of Query-3 is a number (493672033308) which is further used in Query-4
Query-4: SELECT SCN_TO_TIMESTAMP(493672033308) FROM DUAL;
Output-4 is last updated time of specific table MYTABLE_1
How to combine all of this to get a list of all user tables with a total of 3 columns having column headers TABLE_NAME, TOTAL_ROWS, LAST_UPDATE_TIME
EDIT-2: Final Query:
SELECT t.TABLE_NAME
, m.TIMESTAMP
, t.NUM_ROWS
, ((NVL(t.NUM_ROWS,0) + m.INSERTS) - m.DELETES) AS TOT_ROWS
FROM USER_TABLES t
LEFT OUTER JOIN USER_TAB_MODIFICATIONS m
ON t.TABLE_NAME = m.TABLE_NAME
ORDER BY t.TABLE_NAME;
Thanks APC, StevieG, bob dylan :)
Upvotes: 2
Views: 2809
Reputation: 146349
You want to use the contents of the data dictionary to drive a query. This can only be done with dynamic SQL, in a procedure.
Some points to bear in mind:
So a robust solution is quite complex. This one uses DBMS_OUTPUT to display the results; other mechanisms are available:
declare
n pls_integer;
max_scn number;
x_scn_too_old exception;
pragma exception_init(x_scn_too_old ,-08181);
txt varchar2(30);
begin
for lrec in ( select table_name from user_tables )
loop
execute immediate
'select count(*), max(ora_rowscn) from '
|| lrec.table_name
into n, max_scn;
dbms_output.put(lrec.table_name
||' count='||to_char(n));
begin
if n > 0 then
select to_char(scn_to_timestamp(max_scn), 'yyyy-mm-dd hh24:mi:ss.ff3')
into txt
from dual;
else
txt := null;
end if;
exception
when x_scn_too_old then
txt := ('earlier');
end;
dbms_output.put_line(' ts='||txt );
end loop;
end;
/
There is a pure SQL alternative, using NUM_ROWS from USER_TABLES and the USER_TAB_MODIFICATIONS view. This view is maintained by Oracle to monitor the staleness of statistics on tables. As you're on 10g this will be happening automatically (in 9i we had to switch on monitoring for specific tables).
USER_TAB_MODIFICATIONS gives us numbers for the DML activity on each table, which is neat because we can add those numbers to NUM_ROWS to get an accurate total, which is much more efficient than issuing a COUNT().
Again a couple of points.
So here it is:
select t.table_name
, m.timestamp
, t.num_rows
, ((nvl(t.num_rows,0) + m.inserts) - m.deletes) as tot_rows
from user_tables t
left outer join USER_TAB_MODIFICATIONS m
on t.table_name = m.table_name
order by t.table_name
/
Perhaps the best solution is a combination, using NUM_ROWS and USER_TAB_MODIFICATIONS to avoid the count, and only checking ORA_ROWSCN for tables with fresh statistics.
Note that this is only a concern because you don't have your own journalling or table audit. Many places add metadata columns on their tables to track change data (e.g. CREATED_ON, CREATED_BY, UPDATED_ON, UPDATED_BY).
Upvotes: 1
Reputation: 1498
I don't have enough rep to post a comment however the reason why StevieG's answer is still returning an error is because you don't have access to the dba_tab_modifications view, instead use user_ / all_ equivalents in-line with your permissions:
SELECT a.OWNER, a.TABLE_NAME, a.NUM_ROWS, b.TIMESTAMP
FROM ALL_TABLES a
INNER JOIN ALL_TAB_MODIFICATIONS b ON a.OWNER = b.TABLE_OWNER AND a.TABLE_NAME = b.TABLE_NAME
Upvotes: 1
Reputation: 8729
I'd do it like this:
SELECT a.OWNER, a.TABLE_NAME, a.NUM_ROWS, b.TIMESTAMP
FROM ALL_TABLES a
INNER JOIN DBA_TAB_MODIFICATIONS b ON a.OWNER = b.TABLE_OWNER AND a.TABLE_NAME = b.TABLE_NAME
edit - This is correct, except for NUM_ROWS might not be fully accurate: http://www.dba-oracle.com/t_count_rows_all_tables_in_schema.htm
Upvotes: 1