好像每次在批量更新数据库后,就会出现这样的报错。如果把进程重启后,就正常了。
查过这个报错的意思,好像是说申请游标太多的原因。但是我的代码里面能够保证打开的游标最后都会关闭。并且批量更新数据库是用.sql脚本执行的,也不会打开游标吧
所以请教一下,这样的报错会是什么原因呢?

解决方案 »

  1. open_cursors是多少?设大些试试。
      


  2. SQL>  show parameter open_cursors;NAME                                 TYPE        VALUE
    ------------------------------------ ----------- ------------------------------
    open_cursors                         integer     300
      

  3. 贴出存储过程中用到cursor的具体代码,是不是循环嵌套太多了,可能的话,建议调整代码结构
      

  4. 游标有显式游标和隐式游标,像update,delete,insert等语句都会用到游标,还是把代码贴出来吧
      

  5. 不是很理解啊
    我理解的游标是用于读取多条记录的,但是单个的update、delete和insert语句也会用到游标吗?而且对单挑记录的操作都没有定义cursor,更不可能打开游标了,因此也不会存在没有关闭的情况吧!
      

  6. select count(*) from v$open_cursor;
    看看你用了多少游标。把open_cursors设大,一般都几千的。
     
      

  7. 我的open_sursor设置的是300(好像是默认的)
    现在发现300很快就不够用了,用‘select count(*) from v$open_cursor’进行查询,很快就超过300,并且出现ORA-01000的报错。
    跟踪程序发现,任何sql语句的执行都会增加使用的游标数,比如用户登陆这一块:
    void Tran00(struct DATA data)
    {
    EXEC SQL BEGIN DECLARE SECTION;
    char name[20+1];
    char passwd[6+1];
    char lev[2+1];
    int  login_fg;
    EXEC SQL END DECLARE SECTION;
    char c_name[20+1], c_passwd[6+1];

    memset(tmp, SETMEM, sizeof(tmp));
    memset(name, SETMEM, sizeof(name));
    memset(passwd, SETMEM, sizeof(passwd));
    //memcpy(c_name, SETMEM, sizeof(c_name));
    memset(c_passwd, SETMEM, sizeof(c_passwd));

    ret = UnPacket(data.mybuffer);

    strcpy(name, DataItems[0]);
    strcpy(c_passwd, DataItems[1]);
    memset(printbuf, SETMEM, sizeof(printbuf));
    sprintf(printbuf, "用户[%s]登陆\n", name);
    WriteLog(printbuf, DIR);


    EXEC SQL SELECT password,user_lev,login_fg INTO :passwd,:lev,:login_fg
    FROM tb_user_manager
    WHERE user_name = :name;
    if (!SQL_OK){
    if (SQLCODE != SQLNOTFOUND){
    sprintf(tmp, "Trans False [ORA-%05d]\n", SQLCODE);
    WriteLog(tmp, DIR);
    strcpy(outbuf, "02");
    return;
    }else{
    sprintf(tmp, "SQLNOTFOUND\n");
    WriteLog(tmp, DIR);
    strcpy(outbuf, "99");
    return;
    }
    } if (login_fg == 1){
    WriteLog("111\n", DIR);
    strcpy(outbuf, "05");
    WriteLog("222\n", DIR);
    return;
    } if (strncmp(passwd, c_passwd, 6)){
    strcpy(outbuf, "03");
    return;
    } EXEC SQL UPDATE tb_user_manager SET login_fg = 1 WHERE user_name = :name;
    EXEC SQL COMMIT;

    WriteLog("交易成功!!\n", DIR);
    sprintf(outbuf, "00|%s|", lev);

    return;
    }
    登陆成功,游标数增加2,如果密码错误(后面的update没有执行到),游标数增加1.
    但是为什么游标数只有增加,却没有减少的情况呢?如果总是不断的增加,即使设置再大,也无济于事。
    所以请高手帮我看看,是哪里出了问题?
    谢谢!
      

  8. 1) 基本上是C++代码问题。
    2) 增加open_sursor 可以延缓错误的发生。
      


  9. 如果是代码的问题,请明示问题出在哪里了?
    增加open_cursor只能延缓错误的发送,但是不能从根本解决不明白的是,像这样的隐式游标,系统为什么没有自动释放?因为我的数据库是保持连接的,只有进程退出的时候才会断开与数据库的连接。不知道这样的情况下,如何释放游标?
      

  10. EXEC ORACLE OPTION (RELEASE_CURSOR = YES);
      

aliyun

类似问题 »