1

I'm getting ORA-1006 error, "bind variable doesn't exists"

Below is my snippet of code

create or replace procedure bindFailure(In_cntAcct, In_custAcct, In_CardNo, In_Code) AS
  txnHdl INTEGER;
begin
   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(txhHdl, sqlStmt, DBMS_SQL.NATIVE);

   dbms_sql.bind_variable(txnHdl, ':IN_CNTACCT'  , In_cntAcct);
   dbms_sql.bind_variable(txnHdl, ':IN_CUSTACCT' , In_custAcct);
   dbms_sql.bind_variable(txnHdl, ':IN_CARDNO'   , In_CardNo);
   dbms_sql.bind_variable(txnHdl, ':IN_CODE'     , In_Code);

   dbms_sql.execute(txnHdl);

   .... /* In actual code we use fetch rows */

end;
/

Here, cntAcct, custAcct are Number, cardNo and Code are Varchar2

Most of the time above code works fine, but rarely once in 100K this code failed with error "binding variable doesn't exists".

If we take the same input and process, it works fine. I'm not able to figure out, why we are having this issue. Please help me on this.

Note: above code is snippet and i manually typed if any typo issue please ignore.

Thank you, Premchand C

4

1 回答 1

1

作为一种解决方法,您可以避免使用动态 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 支持的指导下。)

问:

您有多确定是bind_variable过程中的调用引发了异常。ORA-1006 异常是否包含在 ORA-06502 异常中?(我希望是。如果不是,那么它实际上可能是一个 JDBC 会话,它将变量绑定到引发异常的过程。)

我很想为过程的每个输入参数创建一个局部过程变量,然后将输入参数分配给局部过程变量。我也很想放入一个异常处理程序,所以我可以审计这个问题:

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;
于 2013-07-23T19:50:58.033 回答