名前付きパラメータを使用してPL/SQLブロックを呼び出すと、すべての名前付きパラメータを1回だけ使用すると、コードは正常に機能しますが、「//SQL」でマークされたSQLを複製するとエラーが発生します。次に、すべての名前付きパラメーター(コロン、:qで始まる)が2回使用され、SQL例外が発生します。パラメーター名の数が、登録されているパラメーターの数と一致しません。JDBCドライバーまたはDBは2つのパラメーターがあると考えているようですが、登録されているパラメーターは1つだけですか?名前付きパラメーターを複数回使用できないのはなぜですか?このケースをサポートするためにJDBCドライバーは必要ありませんか?代替手段(PL / SQLブロックをストアドプロシージャに書き換える実行)を取得するにはどうすればよいですか?
私のOracleJDBCDriverは最新バージョン11.2.0.3.0です。
私のプロジェクトには多くのPL/SQLブロックがあるため、SQLをストアドプロシージャに書き直さないように最善を尽くしています。名前付きパラメータを使用して生のPL / SQLブロックを実行することをお勧めします(プロシージャとして扱うだけです)。PL / SQLブロックをストアド・プロシージャに変換してから、1つのパラメータのみをエクスポートしてテストしましたが、すべてのPL / SQLブロックを書き直したくないので、さらに手間がかかります。
ヒントをありがとう。
私のJavaコード:
CallableStatement stmt = ...;
stmt.registerOutParameter("q", Types.VARCHAR);
stmt.execute();
String v1 = stmt.getString("q");
以下のSQL:
BEGIN
select DUMMY into :q from dual where dummy = 'X';
select DUMMY into :q from dual where dummy = 'X';
EXCEPTION
WHEN NO_DATA_FOUND THEN
NULL;
END;
動的SQLがPL/SQLブロック(beginとendで引用)の場合、「Execute Immediate」を使用できることがわかりました。名前の付いた名前付きパラメータは、すべてのオカレンスで参照できます。つまり、以下に添付されているSQL、このブロックでは、パラメータ'q'は1回だけ使用されますが、もう2つの質問があります。Q1:パラメータ' q'がIN、OUT、またはINとOUTの両方であるかどうかわかりません。間違ったIN/OUTモードを指定すると、エラーが発生します。パラメータがIN / OUTであるか、またはその両方であるかをどのようにテストしますか?SQLで「:q:=」と「into:q」をスキャンしたいのですが、これは適切な方法ではないようです。Q2:パラメータ「q」がIN OUTモードに割り当てられていると、その結果を取得できないのはなぜですか?OUTの場合のみ、その値を取得できます。両方がINOUTの場合、NULLになります。
begin
execute immediate 'begin select dummy into :q from dual where :q is not null; end;'
using in out :q;
end;
ああ、パラメータがIN OUTモードの場合、NULLの回避策があります。これは、OracleJDBCドライバのバグとして扱います。名前付きパラメータ「q」のIN/OUTの役割を2つの部分に分割します。最初はIN、2番目はOUT、変数を使用して'using in out:q'句によって返される値を保持し、変数を以下のように2番目の役割に割り当てます-添付のように、JDBCでは両方をIN OUTとして扱い、正確なIN、OUT、またはINのみを使用します':q:='および'を:q'にスキャンした後のUSING句のOUT。
declare
p varchar2(100);
q varchar2(100);
begin
p := ?;
q := ?;
execute immediate 'begin if :p is null then :p := ''X''; else :p := ''Y''; :q := ''Z''; end if; end;' using in out p, out q;
? := p;
? := q;
end;