I am entirely new to PL/SQL programming..
My requirement is to collect table list under a specific schema, its count(*) and num_rows along with last_analyzed date for n number of databases and populate it into a single table. I am trying to access remote databases via DB link. Managed to write below code with the help of internet sources. But not able to get the output. Please help on this..
CREATE OR REPLACE PROCEDURE fetch_tables_stats
AS
BEGIN
FOR src_link IN (SELECT db_link FROM dba_db_links WHERE USERNAME = '<user>')
LOOP
FOR tbl IN (SELECT table_name FROM dba_tables@src_link.db_link WHERE owner = '<owner>')
LOOP
DECLARE
v_row_count NUMBER;
v_num_rows NUMBER;
sql_stmt1 VARCHAR2(1000);
sql_stmt2 VARCHAR2(1000);
BEGIN
sql_stmt1 := 'SELECT COUNT(*) FROM ' || tbl || '.' || table_name || '@' ||src_link || '.' || db_link;
EXECUTE IMMEDIATE sql_stmt1 INTO v_row_count;
sql_stmt2 := 'SELECT num_rows FROM dba_tab_statistics@' || src_link || '.' || db_link || ' WHERE table_name = ' || tbl ||'.' || table_name || ' AND owner = ' || q'['<owner>']';
EXECUTE IMMEDIATE sql_stmt2 INTO v_num_rows;
INSERT INTO SWMS_TAB_COUNT_STATS_RDS (OPCO_NAME,TABLE_NAME,ACTUAL_ROWCOUNT,STATS_NUM_ROWS,STATS_DATE)
VALUES (src_link.db_link,tbl.table_name, v_row_count, v_num_rows,sysdate);
COMMIT;
END;
END LOOP;
END LOOP;
END fetch_tables_stats;
/
Output:
LINE/COL ERROR
-------- -----------------------------------------------------------------
6/17 PL/SQL: ORA-00942: table or view does not exist
6/17 PL/SQL: SQL Statement ignored
14/6 PL/SQL: Statement ignored
14/46 PLS-00364: loop index variable 'TBL' use is invalid
16/3 PL/SQL: Statement ignored
16/16 PLS-00306: wrong number or types of arguments in call to '||'
18/6 PL/SQL: SQL Statement ignored
19/34 PLS-00364: loop index variable 'TBL' use is invalid
19/38 PL/SQL: ORA-00984: column not allowed here
SQL>
Able to create procedure now.. But it is not populating data inside the table..
SQL> create or replace procedure fetch_tables_stats
as
begin
declare
rc sys_refcursor;
l_table_name dba_tables.table_name%type;
v_row_count number;
v_num_rows NUMBER;
v_last_analyzed NUMBER;
sql_stmt1 VARCHAR2(1000);
sql_stmt2 VARCHAR2(1000);
sql_stmt3 VARCHAR2(1000);
begin
for src_link in (select db_link from user_db_links)
loop
open rc for 'select table_name from dba_tables@' || src_link.db_link || 'where owner = ' || q'['SWMS']';
loop
fetch rc into l_table_name;
exit when rc%notfound;
sql_stmt1 := 'select count(*) from ' || l_table_name ||'@'|| src_link.db_link;
execute immediate sql_stmt1 into v_row_count;
sql_stmt2 := 'SELECT num_rows,last_analyzed FROM dba_tables@' || src_link.db_link || ' WHERE table_name = ' || l_table_name || ' AND owner = ' || q'['SWMS']';
execute immediate sql_stmt2 into v_num_rows, v_last_analyzed;
sql_stmt3 := 'INSERT INTO SWMS_TAB_COUNT_STATS_RDS (OPCO_NAME,TABLE_NAME,ACTUAL_ROWCOUNT,STATS_NUM_ROWS,STATS_DATE)
VALUES (' || src_link.db_link || ',' || l_table_name || ', v_row_count, v_num_rows,v_last_analyzed)';
execute immediate sql_stmt3;
commit;
end loop;
close rc;
end loop;
end;
end fetch_tables_stats;
/ 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
Procedure created.
SQL> exec fetch_tables_stats;
PL/SQL procedure successfully completed.
SQL> select count(*) from SWMS_TAB_COUNT_STATS_RDS;
COUNT(*)
----------
0
As you have to include table name and database link name into query, you'll need dynamic SQL.
Here's an example; I'm using
user_...tables as I don't have access todba_...ones so - you'll have to fix that. Also, I'm just displaying the output to the screen - you'll insert that into a table (fix it as well).[EDIT]
Your procedure has some errors, for example
WHEREinRCSQL_STMT2V_LAST_ANALYZEDvariable (should beDATE, notNUMBER)dbms_output.put_line) and then, when you're sure that it looks OK, actually run it usingexecute immediate. Without it, you can't be really sure what you're trying to executeWhen fixed, it works:
Sample target table:
Procedure (I used
all_tablesand my own user,mike):Testing: