我必须制作一个监视器来检测不同 DBlink 的无效对象。
我尝试过在每个 DBLink 的不同文件中使用代码
-- Enable logging of results to a specific file
SPOOL C:\route
SET SERVEROUTPUT ON
DECLARE
v_count NUMBER := 0;
-- Define a record type to store details of invalid objects
TYPE obj_details_type IS RECORD (
owner VARCHAR2(100),
object_name VARCHAR2(100),
status VARCHAR2(100),
object_type VARCHAR2(100)
);
-- Define a table type to store the details of invalid objects
TYPE obj_details_table IS TABLE OF obj_details_type;
-- Declare a variable to store details of invalid objects
obj_details_list obj_details_table := obj_details_table();
BEGIN
-- Get details of invalid objects
FOR obj IN (SELECT owner, object_name, status, object_type
FROM dba_objects@DBLINK
WHERE status = 'INVALID') LOOP
-- Increase the counter
v_count := v_count + 1;
-- Store details in a collection
obj_details_list.EXTEND;
obj_details_list(obj_details_list.LAST) := obj_details_type(obj.owner, obj.object_name, obj.status, obj.object_type);
END LOOP;
-- Show the number of invalid objects
DBMS_OUTPUT.PUT_LINE('No: of invalid objects: ' || v_count);
-- Show results as a table if there are invalid objects
IF v_count > 0 THEN
-- Print column headers with lines and separations
DBMS_OUTPUT.PUT_LINE('DBLINK: - DATE, TIME: ' || TO_CHAR(SYSDATE, 'DD-MON-YYYY HH24:MI:SS'));
DBMS_OUTPUT.PUT_LINE('-------------------------------------------------------------------------------');
DBMS_OUTPUT.PUT_LINE('-------------------------------------------------------------------------------');
DBMS_OUTPUT.PUT_LINE('|' || RPAD('OWNER', 19) || '|' || RPAD('OBJECT NAME', 30) || '|' || RPAD('STATUS', 7) || ' |' || 'OBJECT TYPE' || ' |');
DBMS_OUTPUT.PUT_LINE('-------------------------------------------------------------------------------');
-- Show details of invalid objects stored in the collection
FOR i IN 1..obj_details_list.COUNT LOOP
-- Imprimir cada fila en formato tabular con líneas y separaciones
DBMS_OUTPUT.PUT_LINE('|' || RPAD(obj_details_list(i).owner, 19) || '|' || RPAD(obj_details_list(i).object_name, 30) || ' |' || RPAD(obj_details_list(i).status, 7) || ' |' || obj_details_list(i).object_type || ' |');
DBMS_OUTPUT.PUT_LINE('-------------------------------------------------------------------------------');
END LOOP;
ELSE
DBMS_OUTPUT.PUT_LINE('No invalid objects were found.');
END IF;
-- Close the database link
EXECUTE IMMEDIATE 'ALTER SESSION CLOSE DATABASE LINK DBLINK';
END;
/
SET SERVEROUTPUT OFF
-- Disable results recording
SPOOL OFF
问题是日志显示,打开链接的最大数量是 4,这就是为什么我在每个文件中添加
EXECUTE IMMEDIATE 'ALTER SESSION CLOSE DATABASE LINK DBLINK
但日志显示:
ERROR in line 1:
ORA-02080: database link is in use
ORA-06512: in line 49
-- Define a record type to store details of invalid objects
*
ERROR in line 3:
ORA-04052: An error occurred while querying the remote object
DBLINK
ORA-00604: An error occurred at recursive SQL level 1
ORA-02020: too many database links in use
我在想是否有一种更简单的方法可以通过查询多个 DBLink 来实现这一点(我只有连接数据库、数据字典查询和创建数据库链接的权限)我也想知道是否有一种方法可以使第一个代码工作没有错误。有什么想法吗?
您无法关闭在尝试关闭数据库链接的同一个 PL/SQL 块中直接作为依赖项引用的数据库链接。您自己的会话就是使用它的会话,因为您仍在执行该 PL/SQL 块。解决方案是使用
EXECUTE IMMEDIATE
或引用光标 OPEN FOR
来删除依赖关系,并使用 动态 SQL 查询远程数据库。
将链接名称分配给局部变量(例如
var_my_link
)。然后是这样的:
DECLARE
var_my_link := 'DBLINK';
cur_remote sys_refcursor;
TYPE obj_details_type IS RECORD (
owner VARCHAR2(100),
object_name VARCHAR2(100),
status VARCHAR2(100),
object_type VARCHAR2(100)
);
-- Define a table type to store the details of invalid objects
TYPE obj_details_table IS TABLE OF obj_details_type;
-- Declare a variable to store details of invalid objects
obj_details_list obj_details_table := obj_details_table();
OPEN cur_remote FOR 'SELECT owner, object_name, status, object_type
FROM dba_objects@'||var_my_link||'
WHERE status = ''INVALID''';
FETCH cur_remote BULK COLLECT INTO obj_details_list;
-- do stuff
CLOSE cur_remote;
EXECUTE IMMEDIATE 'ALTER SESSION CLOSE DATABASE LINK '||var_my_link;