2009-07-18 7 views
1

J'ai un grand nombre de déclarations INSERT à exécuter. Au fur et à mesure que je les exécute, je comprends que "les curseurs ouverts maximum ont été dépassés".État du curseur invalide lors de la tentative de fermeture

OK Oracle, je vais donc fermer les curseurs immédiatement après avoir exécuté les instructions INSERT.

 
SQLCloseCursor(hStmt) 

Mais Oracle dit à cet état "Invalid curseur."

Pourquoi Oracle n'est-il pas content que je ferme le curseur? J'ai testé ce même type de requête via un MySQL dsn et MySQL ne semble pas se plaindre de fermer un curseur immédiatement après une instruction INSERT.

modifier -

Voici le code qui exécute la requête

CHECK est une fonction qui vérifie une erreur SQLResult et les journaux si tout retour TRUE en cas de succès, FALSE si l'échec. "status()" utilise SQLGetDiagRec() pour enregistrer le reste des informations d'erreur.

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

J'appelle nonquery comme si

 
nonquery("sql statement") ; 

Je suis en train de: (qui pourrait être dû à une instruction INSERT n'a pas de curseur)

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

Dans un premier temps,, et plus tard, après de nombreux inserts (nonquery est simplement appelé beaucoup, plusieurs fois de suite), je reçois

 
ORA-01000: maximum open cursors exceeded 

Répondre

1

J'ai un grand nombre de déclarations INSERT à exécuter. Comme je les exécute, je comprends que "maximum ouvert curseurs dépassés".

En fait, cela n'a pas de sens pour moi - les instructions INSERT n'utilisent pas de curseur. Êtes-vous sûr que c'est l'erreur que vous obtenez ceci expliquerait pourquoi vous obtenez:

SQLCloseCursor (hstmt)

Mais Oracle dit à cet « état non valide du curseur. »

car il n'y aurait pas de curseur.

Le fait que MySQL ne se plaint pas pourrait être dû à des différences dans les pilotes. Sont-ils tous les deux ODBC 3.0?

Modifier: Après avoir regardé votre code, j'ai deux questions. Premièrement, pourrions-nous voir les commandes SQL qui causent le problème? Deuxièmement, SQLRowCount est une fonction un peu douteuse - de nombreuses bases de données ne peuvent pas le supporter pour certains types de requêtes, et je peux voir comment il pourrait avoir besoin d'un curseur lui-même. Pouvez-vous essayer d'utiliser une version de votre fonction qui n'appelle pas SQLRowCount?

Edit2: Pensez que Alan a identifié votre problème.Vous libérez une instruction, puis appelez le curseur clopse - ceci n'est pas défini par ODBC. Si vous pensez vraiment que vous devez fermer un curseur (ce que je ne fais pas), fermez-le avant de libérer l'instruction.

+0

http://dev.mysql.com/doc/refman/5.1/en/connector-odbc-versions.html dit le pilote MySQL est « Niveau 1 et niveau 2 ". Je crois que mon pilote oracle doit être ODBC 2 http://www.oracle.com/technology/software/tech/windows/odbc/index.html Je pense qu'il est logique que l'instruction d'insertion ne possède pas de curseur .. mais comment est-ce que je continue à "dépasser les curseurs maximum"? – bobobobo

+0

MSDN indique que «curseur non valide» est uniquement renvoyé par un pilote 3.0. Je voudrais oublier MySQL et se concentrer sur Oracle - pouvez-vous poster un petit exemple qui illustre le problème? Vous pouvez également poster la question sur un site plus orienté Oracle car j'ai l'impression qu'il n'y a pas trop d'utilisateurs réguliers - je crains de ne pas le faire moi-même. –

0

encarts font utiliser un curseur. Si vous faites beaucoup d'insertions, vous devriez réutiliser le curseur. Le modèle doit être

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

Dans votre cas, je ne vois pas un curseur explicite ouvert, donc je suppose que vous comptez sur C++ pour gérer qu'implicitement, et il ne semble pas faire un bon travail. A en juger par le code here, vous devez adapter SQLPrepare dans la logique.

+0

Vous dites "inserts utilisent un curseur" - une preuve de cela? Ils ne le font certainement pas sur Sybase, SQLServer ou MySQL, ou si je me souviens bien, selon le standard SQL. –

+0

Il me peut une chose de terminologie. http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14354/chapter2.htm#sthref73 « Oracle déclare implicitement un curseur pour toutes les instructions de manipulation de définition des données et des données, y compris les instructions SELECT (requêtes) que retourner une seule ligne " –

1

Je pense que vous fermez le curseur deux fois:

SQLFreeStmt(SQL_ CLOSE) - De l'MSDN: « ferme le curseur associé à StatementHandle (si l'on a été défini) et annule tous les résultats en attente »

Par conséquent, L'appel de SQLCloseCursor renvoie un "état de curseur invalide" (voir Note).

Je pense que ce dont vous avez besoin est:

SQLCloseCursor(hStmt); 

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

+1 Oui - ce sera certainement un problème! Je ne sais pas comment j'ai raté cela :-( –

+0

Vous semblez avoir modifié votre message rapidement, donc je ne peux pas voir l'histoire - une mauvaise fonction SO. Bit ne complique pas les choses - une fois que vous appelez SQLFreeStmt, vous ne pouvez pas plus utiliser le handle de déclaration, et tjhis semble être le problème de l'interrogateur, pas les trucs de curseur, qui je pense est hareng rouge. –

Questions connexes