提问人:Asha Ganesan 提问时间:8/30/2023 最后编辑:Asha Ganesan 更新时间:8/31/2023 访问量:61
使用 DB Link 从远程表中获取数据的 PL/SQL 过程
PL/SQL procedure to fetch data from remote tables using DB Link
问:
我是PL / SQL编程的新手。
我的要求是收集特定架构下的表列表、其计数 (*) 和num_rows以及 n 个数据库last_analyzed日期并将其填充到单个表中。我正在尝试通过数据库链接访问远程数据库。在互联网资源的帮助下设法编写了以下代码。但无法获得输出。请帮忙。.
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;
/
输出:
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>
现在可以创建程序..但它不会填充表中的数据。.
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
答:
1赞
Littlefoot
8/30/2023
#1
由于您必须在查询中包含表名和数据库链接名,因此您需要动态 SQL。
下面是一个示例;我正在使用表格,因为我无权访问表格,所以 - 你必须解决这个问题。另外,我只是将输出显示到屏幕上 - 您将将其插入到表格中(也修复它)。user_...
dba_...
SQL> set serveroutput on
SQL> declare
2 rc sys_refcursor;
3 l_table_name user_tables.table_name%type;
4 l_cnt number;
5 begin
6 for src_link in (select db_link from user_db_links) loop
7
8 open rc for 'select table_name from user_tables@' || src_link.db_link;
9
10 loop
11 fetch rc into l_table_name;
12 exit when rc%notfound;
13
14 execute immediate 'select count(*) from ' || l_table_name ||'@'|| src_link.db_link
15 into l_cnt;
16
17 dbms_output.put_line(l_table_name||'@'|| src_link.db_link ||' -> ' || l_cnt || ' row(s)');
18 end loop;
19
20 close rc;
21 end loop;
22 end;
23 /
BONUS@DBL_MIKE -> 0 row(s)
DUMMY@DBL_MIKE -> 1 row(s)
SALGRADE@DBL_MIKE -> 5 row(s)
DEMO_TAGS@DBL_MIKE -> 6 row(s)
<snip>
PL/SQL procedure successfully completed.
SQL>
[编辑]
例如,您的过程存在一些错误
- 缺少前面的空间
WHERE
RC
- 缺少将表名括起来的单引号
SQL_STMT2
- 变量的数据类型错误(应该是 ,而不是
V_LAST_ANALYZED
DATE
NUMBER
) - 良好的实践表明,在使用动态 SQL 时,您应该首先显示要执行的语句 (using ),然后,当您确定它看起来没问题时,实际使用 .没有它,你就无法真正确定你要执行什么
dbms_output.put_line
execute immediate
- 您不需要动态 SQL 将行插入到目标表中;它没有任何动态
- 良好的做法是,您应该避免在循环中提交
修复后,它可以工作:
示例目标表:
SQL> CREATE TABLE swms_tab_count_stats_rds
2 (
3 opco_name VARCHAR2 (30),
4 table_name VARCHAR2 (30),
5 actual_rowcount NUMBER,
6 stats_num_rows NUMBER,
7 stats_date DATE
8 );
Table created.
过程(我使用和我自己的用户,):all_tables
mike
SQL> CREATE OR REPLACE PROCEDURE fetch_tables_stats
2 AS
3 BEGIN
4 DECLARE
5 rc SYS_REFCURSOR;
6 l_table_name all_tables.table_name%TYPE;
7 v_row_count NUMBER;
8 v_num_rows NUMBER;
9 v_last_analyzed DATE;
10 sql_stmt1 VARCHAR2 (1000);
11 sql_stmt2 VARCHAR2 (1000);
12 BEGIN
13 DELETE FROM swms_tab_count_stats_rds;
14
15 FOR src_link IN (SELECT db_link FROM all_db_links)
16 LOOP
17 OPEN rc FOR
18 'select table_name from all_tables@'
19 || src_link.db_link
20 || ' where owner = '
21 || q'['MIKE']';
22
23 LOOP
24 FETCH rc INTO l_table_name;
25
26 EXIT WHEN rc%NOTFOUND;
27 sql_stmt1 :=
28 'select count(*) from ' || l_table_name || '@' || src_link.db_link;
29
30 EXECUTE IMMEDIATE sql_stmt1
31 INTO v_row_count;
32
33 sql_stmt2 :=
34 'SELECT num_rows, last_analyzed FROM all_tables@'
35 || src_link.db_link
36 || ' WHERE table_name = '
37 || CHR (39)
38 || l_table_name
39 || CHR (39)
40 || ' AND owner = '
41 || q'['MIKE']';
42
43 EXECUTE IMMEDIATE sql_stmt2
44 INTO v_num_rows, v_last_analyzed;
45
46 INSERT INTO swms_tab_count_stats_rds (opco_name,
47 table_name,
48 actual_rowcount,
49 stats_num_rows,
50 stats_date)
51 VALUES (src_link.db_link,
52 l_table_name,
53 v_row_count,
54 v_num_rows,
55 v_last_analyzed);
56 END LOOP;
57
58 CLOSE rc;
59 END LOOP;
60
61 COMMIT;
62 END;
63 END fetch_tables_stats;
64 /
Procedure created.
测试:
SQL> EXEC fetch_tables_stats;
PL/SQL procedure successfully completed.
SQL> SELECT *
2 FROM swms_tab_count_stats_rds
3 ORDER BY stats_date;
OPCO_NAME TABLE_NAME ACTUAL_ROWCOUNT STATS_NUM_ROWS STATS_DATE
---------- -------------------- --------------- -------------- -------------------
DBL_MIKE BONUS 0 0 17.05.2018 08:57:22
DBL_MIKE SALGRADE 5 5 17.05.2018 22:00:10
DBL_MIKE DUMMY 1 1 17.05.2018 22:00:10
DBL_MIKE DEMO_ORDERS 10 10 06.10.2018 22:01:03
DBL_MIKE APEX$TEAM_DEV_FILES 0 0 06.10.2018 22:01:03
<snip>
评论
0赞
Asha Ganesan
8/31/2023
谢谢你的建议!我能够创建如下程序..但数据未填充到表中。.
0赞
Littlefoot
8/31/2023
为什么不呢?发生了什么事?
0赞
Asha Ganesan
8/31/2023
我附加了修改后的代码..你能审查一下吗?
0赞
Littlefoot
8/31/2023
是的;我审查了它并编辑了我的答案,以显示您应该做什么。请看一看。
0赞
Asha Ganesan
9/1/2023
哇!你匿名救了我的背!非常感谢您教我这个更正:-)上帝保佑你!
评论
num_rows
dba_tab_statistics
dba_tables
dba_tab_modifications
(inserts-deletes)
dba_tab_modifications
num_rows
dba_tables