Неверное состояние курсора при попытке закрыть - PullRequest
1 голос
/ 18 июля 2009

У меня есть большое количество INSERT-инструкций для запуска. Когда я запускаю их, я понимаю, что «превышено максимальное количество открытых курсоров».

ОК, Oracle, поэтому я закрою курсоры сразу после выполнения операторов INSERT.

SQLCloseCursor( hStmt )

Но Oracle говорит этому «Недопустимое состояние курсора».

Почему Oracle недоволен тем, что я закрываю курсор? Я тестировал этот же тип запроса через MySQL 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 ]

1 голос
/ 19 июля 2009

Я думаю, вы дважды закрываете курсор:

SQLFreeStmt(SQL_ CLOSE) - из MSDN : " Закрывает курсор, связанный с StatementHandle (если он был определен), и отбрасывает все ожидающие результаты "

Следовательно, вызов SQLCloseCursor вернет «Недопустимое состояние курсора» (см. Примечание ).

Я думаю, что вам нужно:

SQLCloseCursor(hStmt);

SQLFreeHandle(SQL_HANDLE_STMT,hStmt) // replace SQLFreeStmt with this
1 голос
/ 18 июля 2009

У меня есть большое количество ВСТАВКИ Уставы для запуска. Когда я их запускаю, я понятно получить "максимально открытый превышены курсоры ".

На самом деле, это не имеет смысла для меня - операторы INSERT не используют курсор. Вы уверены, что это ошибка, которую вы получаете? Это объясняет, почему вы получаете:

SQLCloseCursor (hStmt)

Но Оракул говорит на это "Неверно состояние курсора. "

так как не было бы курсора.

Тот факт, что MySQL не жалуется, может быть из-за различий в драйверах. Они оба ODBC 3.0?

Редактировать: Посмотрев на ваш код, у меня два вопроса. Во-первых, можем ли мы увидеть команды SQL, которые вызывают проблему? Во-вторых, SQLRowCount - это довольно сомнительная функция - многие базы данных не могут поддерживать его для определенных типов запросов, и я вижу, как может потребоваться сам курсор. Можете ли вы попробовать использовать версию вашей функции, которая не вызывает SQLRowCount?

Edit2: Подумайте, что Алан определил вашу проблему. Вы освобождаете оператор и затем вызываете курсор закрытия на нем - это не определено ODBC. Если вы действительно думаете, что вам нужно закрыть курсор (чего я не делаю), закройте его перед освобождением оператора.

0 голосов
/ 19 июля 2009

Вставки используют курсор. Если вы делаете много вставок, вы должны повторно использовать курсор. Шаблон должен быть

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

В вашем случае я не вижу явного открытого курсора, поэтому я предполагаю, что вы полагаетесь на c ++ для неявного управления этим, и, похоже, он не справляется с работой. Судя по коду здесь вам нужно вписать SQLPrepare в логику.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...