5

私の手順は次のようになります。

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;

上記の手順はコンパイルされますが、実行すると次のエラーが発生します。

ソケットから読み取る
データはありませ
んソケットから読み取るデータはありません ソケットから読み取るデータはありません
ソケットから読み取るデータはありません ソケットから読み取るデータはありません ソケット
から
読み取るデータはありません ソケットから
読み取るデータは
ありません いいえmore data to read from socket
...(Few more 'No more data to read from socket')

IO エラー: ピアによる接続のリセット: ソケット書き込みエラー
プロセスが終了しました。

興味深いのは、内側のループ全体をコメントアウトすると、手順がエラーなしで実行されることです。したがって、内側のループに何か問題があることはわかっています (内側のループ内の挿入ステートメントのみにコメントを付けてみましたが、同じエラーが発生しました)。

私のlocaldbdblink1データベースはどちらも同じバージョンです:

Oracle Database 11g Enterprise Edition リリース 11.2.0.1.0 - 64 ビット製品

PL/SQLリリース11.2.0.1.0 - 本番

コア 11.2.0.1.0 プロダクション

64 ビット Windows 用の TNS: バージョン 11.2.0.1.0 - プロダクション

NLSRTL バージョン 11.2.0.1.0 - プロダクション

4

2 に答える 2

5

「ソケットから読み取るデータがありません」エラーのトラブルシューティングに関する一般的なアドバイス。

これらのエラーは通常、ORA-600 エラーなどの別の重大なエラーが原因で発生します。サーバー プロセスがクラッシュし、適切なエラー メッセージをクライアントに送信することさえできないほど深刻な問題。(これらのエラーのもう 1 つの一般的な理由は、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 エラーに関する 1 つ以上の記事があります。正確なバージョンとプラットフォームを使用して、考えられるバグのリストを絞り込みます。(ただし、この記事の「影響を受けるバージョン」が間違っていても驚かないでください。「バージョン xy で修正済み」という Oracle の主張は、常に正しいとは限りません。)

通常、記事では、問題が発生した経緯、考えられる回避策、および通常はパッチまたはアップグレードを伴う解決策について詳しく説明しています。

実際には、これらの問題を解決する必要はほとんどありません。「典型的な」アドバイスは、Oracleサポートに連絡して、実際に同じ問題があることを確認し、パッチを入手し、権限を取得して環境を停止してから、パッチを適用することです。そして、おそらくパッチが機能しないことに気付くでしょう。おめでとうございます、あなたは多くの時間を無駄にしました。

代わりに、クエリまたはプロシージャにわずかな変更を加えることで、通常は問題を回避できます。Oracle には多くの機能があり、ほとんどの場合、それを行う別の方法があります。コードが少し奇妙に見える場合は、将来のプログラマーに警告するコメントを追加してください。

このコードに関する具体的なアドバイス

それが実際に手順全体である場合は、次のようなものに置き換える必要があります。

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 で処理する必要があります。特に、多くのカーソルを開くことを避けることができる場合。特に、リモート データベースに対して多くのカーソルを開かないようにできる場合はなおさらです。

于 2012-09-27T04:26:02.400 に答える
1

jonearles が述べたように、これを 1 つの 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;
/
于 2012-10-25T09:07:32.210 に答える