尝试关闭时无效的游标状态

时间:2009-07-18 18:09:39

标签: c++ oracle odbc

我有大量的INSERT语句要运行。当我运行它们时,我可以理解地得到“超出最大开放游标数”。

确定Oracle,因此我将在运行INSERT语句后立即关闭游标。

SQLCloseCursor( hStmt )

但Oracle对此说“无效的游标状态。”

为什么Oracle对我关闭游标不满意?我通过My​​SQL dsn测试了这种相同类型的查询,并且MySQL似乎没有抱怨在INSERT语句之后立即关闭游标。

编辑 -

以下是执行查询的代码

CHECK是一个检查SQLRESULT并记录错误的函数,如果有的话,如果成功则返回TRUE,如果失败则返回FALSE。 “status()”使用SQLGetDiagRec()记录其余的错误信息。

  SQLINTEGER nonquery( char * nonquery )
  {
    SQLINTEGER rowsAffected = 0 ;

    SQLHANDLE hStmt ;
    CHECK( SQLAllocHandle( SQL_HANDLE_STMT, hConn, &hStmt ), "allocate handle for statement" ) ;

    if( !CHECK( SQLExecDirectA( hStmt, (SQLCHAR*)nonquery, SQL_NTS ), "execute query" ) ) 
    {
      status( SQL_HANDLE_STMT, hStmt, __LINE__ ) ;
    }

    // Get rows affected
    if( !CHECK( SQLRowCount( hStmt, &rowsAffected ), "row count after non-query" ) )
    {
      status( SQL_HANDLE_STMT, hStmt, __LINE__ ) ;
    }

    if( ! CHECK( SQLFreeStmt( hStmt, SQL_CLOSE ), "Sql free stmt" ) )
    {
      status( SQL_HANDLE_STMT, hStmt, __LINE__ ) ;
    }

    // CLose up.
    if( !CHECK( SQLCloseCursor( hStmt ), "close cursor" ) )
    {
      status( SQL_HANDLE_STMT, hStmt, __LINE__ ) ;
    }

    return rowsAffected ;
  }

我称之为非查询

nonquery( "sql statement" ) ;

所以我得到了:

[24000][0] [Oracle][ODBC]Invalid cursor state.

首先,(可能是由于INSERT语句没有游标?),之后,经过多次插入(非查询简单地称为多次,连续多次),我得到了

ORA-01000: maximum open cursors exceeded

3 个答案:

答案 0 :(得分:1)

  

我有大量的INSERT   要运行的语句。当我跑他们的时候,我   可以理解得到“最大限度开放   游标超过了“。

实际上,这对我没有意义 - INSERT语句不使用游标。你确定这是你得到的错误这可以解释你为什么得到:

  

SQLCloseCursor(hStmt)

     

但甲骨文对此说“无效”   光标状态。“

因为没有光标。

MySQL不抱怨的事实可能是由于驱动程序的差异。它们都是ODBC 3.0吗?

修改:看了你的代码,我有两个问题。首先,我们能看到导致问题的SQL命令吗?其次,SQLRowCount是一个有点可疑的功能 - 许多数据库不支持某些查询类型,我可以看到它本身可能需要一个游标。您可以尝试使用不调用SQLRowCount的函数版本吗?

编辑2:认为Alan确定了您的问题。你释放一个语句,然后在它上面调用clopse游标 - 这是ODBC未定义的。如果你真的认为你需要在释放语句之前关闭它(我没有)关闭它。

答案 1 :(得分:1)

我认为你正在关闭光标两次:

SQLFreeStmt(SQL_ CLOSE) - 来自MSDN:“关闭与StatementHandle关联的游标(如果已定义)并丢弃所有待处理结果

因此,调用SQLCloseCursor将返回“无效的游标状态”(参见Note)。

我认为你需要的是:

SQLCloseCursor(hStmt);

SQLFreeHandle(SQL_HANDLE_STMT,hStmt) // replace SQLFreeStmt with this

答案 2 :(得分:0)

插入确实使用游标。如果要进行大量插入,则应该重用光标。 模式应该是

OPEN cursor
  start loop
     BIND variables
     EXECUTE CURSOR
  end loop
CLOSE cursor

在你的情况下,我没有看到一个明确的打开游标,所以我猜你依靠c ++来隐式地管理它,而且它似乎没有做得很好。根据代码here判断,您需要将SQLPrepare放入逻辑中。