我的程序如下:
Declare
cur_1 Sys_Refcursor;
cur_2 Sys_Refcursor;
v_1 VARCHAR2(30);
v_2 VARCHAR2(30);
v_3 VARCHAR2(30);
v_4 VARCHAR2(30);
Begin
OPEN cur_1 for Select * from tab1@dblink1;
Loop
Fetch cur_1 into v_1, v_2;
EXIT WHEN cur_1%NOTFOUND;
OPEN cur_2 for Select * from tab2@dblink1 where col1 = v_1 and col2 = v2;
Loop
Fetch cur2 into v_3, v_4;
Exit when cur_2%notfound;
INSERT INTO local.tab3 values (v_1,v_2, v_3, v_4);
END Loop;
close cur_2;
End Loop;
close cur_1;
END;
abobe程序编译,但是当我运行它时,我得到以下错误:
无法从插座中读取数据
没有更多数据要从插座中读取
没有更多数据要从插座中读取
没有更多数据要从插座中读取
没有更多数据要从插座中读取
没有更多数据要从插座中读取
没有更多数据要从插座中读取
没有更多数据要从插座中读取
......(几乎没有'从套接字中读取更多数据')IO错误:通过对等方重置连接:套接字写入错误
流程退出。
有趣的是,当我注释掉整个内循环时,程序运行时没有错误。所以我知道内部循环有问题(我尝试只在内部循环中注释insert语句并得到相同的错误)。
我的 localdb 和 dblink1 数据库都有相同的版本:
Oracle Database 11g企业版11.2.0.1.0版 - 64位生产
PL / SQL版本11.2.0.1.0 - 生产
CORE 11.2.0.1.0生产
适用于64位Windows的TNS:版本11.2.0.1.0 - 生产
NLSRTL版本11.2.0.1.0 - 生产
答案 0 :(得分:4)
这些错误通常是由另一个严重错误引起的,例如ORA-600错误。一个严重的问题,服务器进程崩溃,甚至无法向客户端发送正确的错误消息。 (这些错误的另一个常见原因是SQLNET.EXPIRE_TIME或其他一些杀死旧会话的进程导致网络断开。)
查看警报日志以找出原始错误消息。
在此目录中查找文件alert_ [name] .log:select value from v$parameter where name = 'background_dump_dest';
找到具体的错误消息和详细信息后,请访问support.oracle.com。使用“ora-600工具”,然后在ORA-600消息之后查找第一个数字。
对于该特定类型的ORA-600错误,通常会有一篇或多篇文章。使用确切的版本和平台来缩小可能的错误列表。 (但如果文章中的“受影响的版本”是错误的,请不要感到惊讶.Oracle声称“修复版本x.y”并非总是如此。)
这些文章通常会更详细地解释问题是如何发生的,可能的解决方法以及通常涉及补丁或升级的解决方案。
在实践中,您很少想解决这些问题。 “典型”建议是联系Oracle支持部门以验证您是否确实遇到了同样的问题,获得了修补程序,获得了许可并关闭了环境,然后应用了修补程序。然后可能意识到补丁不起作用。恭喜你,你浪费了很多时间。
相反,您通常可以通过对查询或过程进行细微更改来避免问题。 Oracle中有很多功能,几乎总有另一种方法可以做到这一点。如果代码看起来有点奇怪,添加注释以警告未来的程序员:“这段代码看起来很奇怪,以避免错误X,应该在版本Y中修复。”
如果这真的是你的整个过程,你应该用这样的东西替换它:
insert into local.tab3(col1, col2, col3, col4)
select tab1.col1, tab1.col2, tab2.col1, tab2.col2
from tab1@dblink1 tab1
join tab2@dblink1 tab2
on tab1.col1 = tab2.col1
and tab1.col2 = tab2.col2;
通常,如果可能,您应该始终在SQL中执行操作。特别是如果你可以避免打开许多游标。如果您可以避免将多个游标打开到远程数据库,那么尤其是。
答案 1 :(得分:1)
正如jonearles所提到的,你应该在一个SQL语句中写这个。
如果你坚持使用PL / SQL:你自己做了太多的工作,声明变量,打开游标,循环,分配变量。考虑一下这个PL / SQL:
begin
for c1 in (select * from tab1@dblink1)
loop
for c2 in (Select * from tab2@dblink1 where col1 = c1.col1 and col2 = c1.col2)
loop
insert into local.tab3 values (c1.col1,c1.col2,c2.col1,c2.col2);
end loop;
end loop;
end;
/