oracle - ORA 1006绑定变量在使用 dbms_sql.bind_variable 函数时不存在

  显示原文与译文双语对照的内容
0 0

i ORA-1006 错误,"变量不存在""

下面是我的代码 Fragment

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;
/

这里,cntAcctcustAcctNumbercardNoCodeVarchar2

上面的代码大部分工作正常,但是在 100K 中很少出现这种代码,错误是"绑定变量不存在"。

如果我们采取同样的输入和处理,它就能正常工作。 我无法清楚我们为什么要把这个问题。 请帮我一下。

注意:上代码为代码段,如果出现错误,请手动键入。

谢谢你 Premchand C

时间:原作者:6个回答

0 0

作为解决方法,你可以避免使用动态 SQL 。 在选择列表中不编码星号(" *"),指定需要返回的列名。 并在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;

原始答案

这是 scratcher,这个代码里没有明显的错误。 ( 考虑过程大多数时候,我将假定指定了参数的数据类型,并且这些都是参数。)

可以以想象,解析工作,你得到一个游标句柄,但光标在所有调用bind_variable完成之前失效。 但我认为这将是一个例外。

如果txnHdl在不知道的情况下获得wonked并指向不同的游标,我可以以在错误的光标上调用 ORA-1006 异常。 ( 但在Oracle代码中这是一个严重的Bug,而不是在你的程序中。 但我从未遇到过这种错误,从未在任何MySQL中都检查过类似的东西。

为了调试这个问题,因为它很少发生,我会打开一个带有Oracle支持的案例,看看是否有异常 ORA-1006. ( 我从来没有为那个事件做过一个集合;我甚至不知道这是否可以以或者者是"客户端"异常。 但是,在Oracle支持的指导下,我会在生产数据库服务器上执行这一操作。

问题:

你认为在引发异常的过程中调用 bind_variable 是如何确定的。 是否在ORA-06502异常中包装了 ORA-1006 异常? ( 我希望是。 如果不是,那么实际上它是一个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;
原作者:
...