2

Oracle(11g) ベースのアプリケーションでは、パイプライン関数を多用しています。以下の (簡略化された) 例に示すように、このような関数からのエラー報告は難しいことがわかりました。プロシージャは Java から呼び出されるように存在し、PL/SQL の実行中にどこかで発生したエラーを受け取ります。

オラクルの部分:

set serveroutput on

create table dummy (id NUMBER);

create or replace package mytest
as
        type t_rec is record (id integer);
        type t_tab is table of t_rec;
        type t_ref_cur IS REF CURSOR RETURN t_rec;

        function foo
        return t_tab pipelined;

        procedure bar( p_ref_cur out t_ref_cur);
end mytest;
/
show errors

create or replace package body mytest
as
        function foo
        return t_tab pipelined
        is
                v_cur SYS_REFCURSOR;
                v_sql varchar2(2000);
                v_rec t_rec;
        begin
                v_sql := 'select wrong_column from DUMMY';
                open v_cur for v_sql;
                loop
                        fetch v_cur into v_rec;
                        exit when v_cur%notfound;

                        pipe row (v_rec);
                end loop;
        exception
                when no_data_needed then
                        null;
                when others then
                        dbms_output.put_line(SQLCODE||' '||sqlerrm );
                        raise no_data_found;
        end foo;

        procedure bar( p_ref_cur out t_ref_cur)
        is
        begin
                open p_ref_cur for select * from table(foo);
        end bar;
end mytest;
/
show errors

-- call procedure bar() from pl/sql
set serveroutput on
declare v_ref_cur mytest.t_ref_cur;
        v_rec mytest.t_rec;
begin
        mytest.bar(v_ref_cur);
        loop
              fetch v_ref_cur into v_rec;
              exit when v_ref_cur%notfound;
              dbms_output.put_line(v_rec.id);
      end loop;
end;
/
show errors

上記の関数を実行すると、例外が表示されます。

ORA-00904: "WRONG_COLUMN": invalid column name

Java 部分:

package test1;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import oracle.jdbc.OracleTypes;

public class start {

    public static void main(String[] args) 
    {
        try 
        {
            Connection con = DriverManager.getConnection("jdbc:oracle:thin:@...", "…", "…");
            CallableStatement stmt = con.prepareCall("BEGIN mytest.bar(?); END;");
            stmt.registerOutParameter(1, OracleTypes.CURSOR);
            stmt.executeQuery();
            ResultSet rs = (ResultSet)stmt.getObject(1);
            while (rs.next())
            {
                System.out.println(rs.getInt(1));
            }
            stmt.close();
            con.close();
        } catch (Exception e) 
        {
            e.printStackTrace();
        }
    }
}

例外はキャッチされません。結果セットが空です。

これは予想される動作ですか?私たちは何か間違ったことをしていますか?回避策はありますか?

4

1 に答える 1