说要在数据库中监控dblink,所以创建一个定时job,如果dblink有问题,job执行就用正确的数据给重新创建一下;如果没有呢,就重新创建一个。就算不使用,新建一个也不受影响。主要代码如下:
SELECT COUNT(1)
INTO v_Count
FROM USER_OBJECTS T
WHERE T.Object_Type = 'DATABASE LINK'
AND T.OBJECT_NAME = UPPER(i_DbLinkName);
BEGIN
IF v_Count >= 1 THEN
v_SqlStr := 'SELECT 0 FROM dual@' || UPPER(i_DbLinkName);
ELSE
v_SqlStr := 'CREATE DATABASE LINK SER_REP_LINK CONNECT TO ' || i_UserName || ' IDENTIFIED BY ' || i_Pwd ||' USING ''' || i_DbAlias || '''';
END IF;
EXECUTE IMMEDIATE v_SqlStr--------STEP1
INTO v_Result;
EXCEPTION
WHEN OTHERS THEN
-- drop DBLink first
v_SqlStr := 'DROP DATABASE LINK SER_REP_LINK';
EXECUTE IMMEDIATE v_SqlStr;--------STEP2
-- rebuild DBLink
v_SqlStr := 'CREATE DATABASE LINK SER_REP_LINK CONNECT TO ' || i_UserName || ' IDENTIFIED BY ' || i_Pwd ||' USING ''' || i_DbAlias || '''';
EXECUTE IMMEDIATE v_SqlStr;
END;
COMMIT;
第一种情况,把dblink using后面的连接字符串改为一个不存在的,job执行后,dblink果然恢复正确。
第二种情况,删除dblink,然后等待job执行去创建一个。但等了很久,sorry,没有。
好吧,调试job对应的procedure。奇了怪了,每次执行到STEP1的时候就奔到Exception里了然后开始drop,在STEP2之后,就出去了,跑到外面的Exception里了。看了下,说是没有找到数据库连接。其实如果STEP1执行成功了,就直接退出不会抛异常的。看了下前面的v_Result,是null。这个值是干什么用的呢?得,注释掉看看。这下可以了。
再把第一种情形跑一下,也pass。
后来问了下oracle专家,如果excute immediate 后面用into的话,前面肯定是select,这里第一种情况下对应的就是select 0 from dual,所以不会有问题,但第二次用的是create database link,不是select,怎么会有Result呢?
不错哈,问题定位出来了,还学习到了一点,乐啊乐啊乐啊……主要是发脚本过来的同事把我的测试结果mail给了PM,说v_Result去掉了,请比对合入代码。