回避策として、動的 SQL の使用を避けることができます。SELECT リストでアスタリスク (" *
") をコーディングする代わりに、返される列名を指定します。また、引数変数を SQL テキストに含めます。Oracle は自動バインドを行います。
CREATE OR REPLACE PROCEDURE ...
IS
CURSOR lcsr_txn IS
SELECT t.cntAcct
, t.custAcct
, t.cardNo
, t.Code
FROM txn t
WHERE t.cntAcct = IN_cntAcct
AND t.custAcct = IN_custAcct
AND t.cardNo = IN_cardNo
AND t.Code = IN_Code
;
BEGIN
FOR lrec IN lcsr_txn LOOP
-- code to process rows goes here e.g.
DBMS_OUTPUT.PUT_LINE("cntAcct="||lrec.cntAcct);
END LOOP;
END;
元の答え
それがヘッドスクラッチャーです。このコードには明らかな問題はありません。(手順がほとんどの場合に機能することを考えると、パラメーターのデータ型が指定されており、これらがすべて IN パラメーターであると仮定します。)
解析が機能し、カーソル ハンドルが返されることは考えられますが、bind_variable へのすべての呼び出しが完了する前にカーソルが無効になります。しかし、それはORA-1006以外の例外になると思います。
txnHdl が何らかの形で異常を起こし、別のカーソルを指している場合、bind_variable
プロシージャが間違ったカーソルで呼び出されると、ORA-1006 例外が発生することがわかりました。(しかし、それはあなたの手順ではなく、Oracleコードの深刻なバグです。しかし、私はそのエラーに遭遇したことはなく、MySQLのいずれかでこのようなことをチェックする必要はありませんでした.
これをデバッグするには、めったに発生しないため、Oracle サポートにケースをオープンし、例外 ORA-1006 が発生するたびにトレース/ダンプを収集できるかどうかを確認します。(私はこれまでにSET EVENTを実行したことがありません。それが可能かサポートされているかさえわかりません。これは「クライアント側」の例外かもしれませんが、サーバー上で実行されているPL/SQLブロックでは、利用できると思います.しかし、特に本番データベースサーバーでは、Oracleサポートのガイダンスの下でこれを行います.)
Q:
bind_variable
例外をスローしているのはプロシージャ内の呼び出しであることをどの程度確信していますか。その ORA-1006 例外は ORA-06502 例外内にラップされていますか? (そうなると思います。そうでない場合、実際には、例外を発生させているプロシージャに変数をバインドしているJDBCセッションである可能性があります。)
プロシージャへの入力パラメータごとにローカル プロシージャ変数を作成し、入力パラメータをローカル プロシージャ変数に代入したくなるでしょう。また、EXCEPTION ハンドラーを挿入したくなるので、問題を監査できます。
CREATE OR REPLACE PROCEDURE bindFailure
( In_cntAcct NUMBER
, In_custAcct NUMBER
, In_CardNo VARCHAR2
, In_Code VARCHAR2
) AS
txnHdl INTEGER;
xn_cntacct txn.cntAcct%TYPE;
xn_custacct txn.custAcct%TYPE;
xn_cardno txn.cardNo%TYPE;
xn_code txn.Code%TYPE;
bind_variable_does_not_exist EXCEPTION;
PRAGMA EXCEPTION_INIT (bind_variable_does_not_exist, 1006);
BEGIN
xn_cntAcct := IN_CntAcct;
xn_custAcct := IN_CustAcct;
xn_cardno := IN_CardNo;
xn_code := IN_Code;
txnHdl := dbms_sql.open_cursor;
sqlStmt := 'select * from txn t'
|| ' where t.cntAcct = :IN_CNTACCT '
|| ' and t.custAcct = :IN_CUSTACCT '
|| ' and t.cardNo = :IN_CARDNO '
|| ' and t.Code = :IN_CODE ';
dbms_sql.parse(txnHdl, sqlStmt, DBMS_SQL.NATIVE);
dbms_sql.bind_variable(txnHdl, ':IN_CNTACCT' , xn_cntacct);
dbms_sql.bind_variable(txnHdl, ':IN_CUSTACCT' , xn_custacct);
EXCEPTION
WHEN bind_variable_does_not_exist THEN
-- auditing here
RAISE;
WHEN OTHERS THEN
RAISE;
END;