关于V$OPEN_CURSOR

在之前的一次讨论中,有同行指出V$OPEN_CURSOR中列出的不是OPEN CURSOR而是SESSION CACHED CURSOR,原因是在一次ORA-01000(maximum open cursors exceeded)事故中他没有从V$OPEN_CURSOR中找到大量的打开游标。

对于这个问题,我们可以利用JAVA程序做一个演示来说明,以下为JAVA代码:

package javaapplication2;
import java.util.logging.Level;
import java.util.logging.Logger;
import oracle.jdbc.*;
import java.sql.*;

public class Main {

    public static void main(String[] args) throws SQLException {
        try {
            Class.forName("oracle.jdbc.driver.OracleDriver");
        }catch(Exception e ){}
   Connection cnn1=DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:G11R2", "maclean", "maclean");

  // Connection m[]=new Connection[2000];
   Connection myconn=DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:G11R2", "maclean", "maclean");

    Statement stat1=myconn.createStatement();
   ResultSet rst1=stat1.executeQuery("select * from v$version");
   while(rst1.next())
   {
       System.out.println(rst1.getString(1));
   }
   rst1=stat1.executeQuery("select distinct sid from v$mystat");

   while (rst1.next()){
   System.out.println("MY SID IS "+rst1.getString(1));
        }

   PreparedStatement s[]=new PreparedStatement[2000];
   PreparedStatement p;
   //ResultSet r[]=new ResultSet[2000];
   int i=0;
   while(i<2000){
    //  m[i]=DriverManager.getConnection("jdbc:oracle:thin:@192.168.1.121:1521:G10R2", "maclean", "maclean");
      //s[i]=m[i].createStatement();
      //m[i].setAutoCommit(false);
      //s[i].execute("insert into testjava values(1)");
       p=myconn.prepareStatement("select /* FIND_ME_OPPO */ * from dual");
       p.execute();

            try {
                Thread.sleep(200);
            } catch (InterruptedException ex) {
                Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
            }

      i++;
      System.out.println(i+" cursor is ok !");
   }
   }
}

以上JAVA代码会打个一个数据库会话,并在循环中不断以prepareStatement对象执行SQL语句,且我们不使用close()方法关闭prepareStatement所打开的游标,实际上这是很多JDBC应用产生ORA-01000问题的主要原因,开发人员在使用prepareStatement时不知道要使用close()方法以回收OPEN CURSOR资源。

注意这里在使用JDBC API时的表现(可能是目前最流行应用形式)和PL/SQL中的游标是存在区别的,在PL/SQL使用close cursor语句并不会真正意义上关闭游标。出于性能的考量,PL/SQL中的游标将被缓存以备将来使用,同时Oracle会维护一张cursor的LRU列表,但如果当本会话的游标数量即将达到open_cursors参数所定义的上限数量时,老的游标将被真正意义上close,以便open后来者。

The following is a technical explanation provided by Oracle Development: 

The server caches cursors opened by the PL/SQL engine.  Each time

a cursor is closed, it is really moved to an Least Recently Used

(LRU) list of open cursors and left open.  This is done as a

performance improvement by saving a ’round_trip’ from Client to Server

each time a cursor is opened.

 

Note that no optimization occurs.  In other words, the cursor caching

code does not check to see if a particular query already has a cursor

open; it simply creates another one.  This is done until OPEN_CURSORS

is reached.  If you have OPEN_CURSORS cached as open, however, then if

an identical query occurs, the server reuses the cached cursor.

可以通过以下语句来了解系统中真正意义上的打开着的游标:

select sum(a.value), b.name
from v$sesstat a, v$statname b
where a.statistic# = b.statistic#
and b.name = 'opened cursors current'
group by b.name;

编译并尝试运行以上程序:

compile:
Created dir: C:\Users\Maclean Liu\Documents\NetBeansProjects\JavaApplication2\dist
Copy libraries to C:\Users\Maclean Liu\Documents\NetBeansProjects\JavaApplication2\dist\lib.
Building jar: C:\Users\Maclean Liu\Documents\NetBeansProjects\JavaApplication2\dist\JavaApplication2.jar
To run this application from the command line without Ant, try:
java -jar "C:\Users\Maclean Liu\Documents\NetBeansProjects\JavaApplication2\dist\JavaApplication2.jar"
jar:
成功生成(总时间:0 秒)

java -jar "C:\Users\Maclean Liu\Documents\NetBeansProjects\JavaApplication2\dist\JavaApplication2.jar"
MY SID IS 392
1 cursor is ok !
2 cursor is ok !
......................

以上程序打开的会话为392,我们来观察392会话的CURSOR情况:

SQL> select * from v$version;

BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production
PL/SQL Release 11.2.0.2.0 - Production
CORE    11.2.0.2.0      Production
TNS for Linux: Version 11.2.0.2.0 - Production
NLSRTL Version 11.2.0.2.0 - Production

SQL> select * from global_name;

GLOBAL_NAME
--------------------------------------------------------------------------------
www.askmac.cn

select sql_text, cursor_type, count(*)
  from v$open_cursor
 where sid = 392
 group by sql_text, cursor_type
 order by 3 desc
/

SQL_TEXT                                                     CURSOR_TYPE                                          COUNT(*)
------------------------------------------------------------ -------------------------------------------------- ----------
select /* FIND_ME_OPPO */ * from dual                        OPEN                                                     1279
select * from v$version                                      OPEN                                                        1
select privilege# from sysauth$ where (grantee#=:1 or grante DICTIONARY LOOKUP CURSOR CACHED                             1
select distinct sid from v$mystat                            OPEN                                                        1
insert into sys.aud$( sessionid,entryid,statement,ntimestamp OPEN-RECURSIVE                                              1
select /*+ connect_by_filtering */ privilege#,level from sys DICTIONARY LOOKUP CURSOR CACHED                             1

可以看到"select /* FIND_ME_OPPO */ * from dual"语句在V$OPEN_CURSOR中存在1279条记录,
且CURSOR TYPE均为OPEN

注意V$OPEN_CURSOR视图中的CURSOR_TYPE列直到11g release 2中才出现,如果该列在9i/10g中就有的话那么可能就不会造成那么多misunderstand了,实际上V$OPEN_CURSOR中的记录来源于X$KGLLK:

SQL> select view_definition
  2    from v$fixed_view_definition
  3   where view_name = 'GV$OPEN_CURSOR';

VIEW_DEFINITION
--------------------------------------------------------------------------------
select inst_id,
       kgllkuse,
       kgllksnm,
       user_name,
       kglhdpar,
       kglnahsh,
       kgllksqlid,
       kglnaobj,
       kgllkest,
       decode(kgllkexc, 0, to_number(NULL), kgllkexc),
       kgllkctp                                              -- CURSOR_TYPE
  from x$kgllk
 where kglhdnsp = 0
   and kglhdpar != kgllkhdl

KGLHDPAR!=KGLLKHDL 该条件排除了父游标,所以V$OPEN_CURSOR列出的均是child cursor
KGLHDNSP ==> NAME SPACE =0 

SQL> select distinct kgllkctp from X$kgllk;

KGLLKCTP
----------------------------------------------------------------
SESSION CURSOR CACHED
PL/SQL CURSOR CACHED
OPEN
OPEN-RECURSIVE
DICTIONARY LOOKUP CURSOR CACHED
BUNDLE DICTIONARY LOOKUP CACHED

以上是六种CURSOR_TYPE,可以看到SESSION CURSOR CACHED和PL/SQL CURSOR CACHED也在其中:

SQL> select kgllkmod, kgllkctp, count(*)
  2    from X$KGLLK
  3   where KGLHDNSP = 0
  4   group by kgllkmod, kgllkctp;

  KGLLKMOD KGLLKCTP                                                           COUNT(*)
---------- ---------------------------------------------------------------- ----------
         1 SESSION CURSOR CACHED                                                    32
         1 DICTIONARY LOOKUP CURSOR CACHED                                          96
         1 OPEN-RECURSIVE                                                           42
         1 PL/SQL CURSOR CACHED                                                     19
         1 OPEN                                                                    216

注意不管是何种CURSOR_TYPE,本质上都是child cursor上的library cache lock,KGLLKMOD=1即这些library cache lock的lock mode均是NULL,也就是breakable parse lock。

Null (N): special for session persistency 

Null locks are special and are only acquired on executable objects (child cursors, procedures, functions, and packages)

A broken null lock means the meta-data has changed.

Null locks are special. They are acquired on objects that are to be executed (child cursor, procedure, function, package, or type body) and they are used to maintain an interest on an object for a long period of time (session persistency), and to detect if the object becomes invalid. Null locks can be broken at any time. This is used as a mechanism to notify a session that an executable object is no longer valid. If a null lock is broken, and thus the object is invalidated, it is an indication to the user who was holding the null lock that the object needs to be recompiled.

A Null lock is acquired during the parse phase of SQL statement execution and is held as long as the shared SQL area for that statement remains in the shared pool. A null lock does not prevent any DDL operation, and can be broken to allow conflicting DDL operations, hence the term breakable parse lock.

A Null lock on an object is broken when there is an exclusive pin on the object. A null lock on a read-only object is broken where there is an exclusive pin on any of the parent objects it depends on.

 

因为CURSOR_TYPE(kgllkctp)列的出现我们在11.2中能够很方便地分辨OPEN CUROSR和SESSION CURSOR CACHED,但如果是在9i/10g/11gr1中则无法通过V$OPEN_CURSOR或X$KGLLK找出哪些是打开游标,另一些是会话缓存游标?

实际上Oracle Support在10g中已经意识到了这个问题,Metalink Note<Bug 7375227 – V$OPEN_CURSOR contains both open cursors and session cached cursors [ID 7375227.8]>说明了该问题:

Bug 7375227  V$OPEN_CURSOR contains both open cursors and session cached cursors
 This note gives a brief overview of bug 7375227.
 The content was last updated on: 10-JUL-2009
 Click here for details of each of the sections below.
Affects:

    Product (Component)	Oracle Server (Rdbms)
    Range of versions believed to be affected	Versions >= 10.2.0.1 but < 11.2
    Versions confirmed as being affected	

        10.2.0.3 

    Platforms affected	Generic (all / most platforms affected)

Fixed:

    This issue is fixed in	

        11.2 (Future Release) 

Symptoms:

Related To:
    Code Improvement
    (None Specified)
    V$OPEN_CURSOR 

Description

    View V$OPEN_CURSOR contains both open cursors and session cached cursors and
    before this fix there was no way to distinguish them.
    This fix adds new column CURSOR_TYPE to V$OPEN_CURSOR which distinguishes
    between open cursors and cursors in the session cache. 

    Values are:
     SYSTEM - recursive sql cursors
     PL/SQL - for open pl/sql cursors
     KNT CACHED, KKS CACHED, PL/SQL CACHED, KQD CACHED, KQD BUNDLE CACHED
     , KXCC CACHED - for cached cursors

Cursor Sharing的相关诊断事件:

[oracle@rh2 ~]$ oerr ora 10270
10270, 00000, "Debug shared cursors"
// *Cause: Enables debugging code in shared cursor management modules
// *Action:

alter session set events '10270 trace name context forever, level 10';

[oracle@rh2 ~]$ oerr ora 10277
10277, 00000, "Cursor sharing (or not) related event (used for testing)"
// *Cause:
// *Action:

 alter session set events '10277 trace name context forever, level 1';

alter session set events  'immediate trace name library_cache level 10';

Comments

  1. Closing the Cursor

    Syntax

    Close the cursor after completing the processing of the rows.
    Reopen the cursor, if required.
    Do not attempt to fetch data from a cursor once it has been closed.

    CLOSE Statement
    The CLOSE statement disables the cursor, and the active set becomes undefined. Close the cursor after completing the processing of the SELECT statement. This step allows the cursor to be reopened, if required. Therefore, you can establish an active set several times.
    In the syntax:
    cursor_name is the name of the previously declared cursor.
    Do not attempt to fetch data from a cursor once it has been closed, or the INVALID_CURSOR exception will be raised.
    Note: The CLOSE statement releases the context area. Although it is possible to terminate the PL/SQL block without closing cursors, you should get into the habit of closing any cursor that you declare explicitly in order to free up resources. There is a maximum limit to the number of open cursors per user, which is determined by the OPEN_CURSORS parameter in the database parameter field. OPEN_CURSORS = 50 by default.

  2. 你好。
    谢谢你精彩的讲述。
    有一个问题想请教一下。

    请问11g在V$OPEN_CURSOR中增加了这个字段,会不会对原来10g的程序造成影响。

    我在10g下编译的Pro*C文件,拿到11g下CURSOR无法关闭了,一直显示open,时间一长,就报ORA-01000的错误,游标超限了。

    还有就是Oracle配置中有一个选项release_cursor是吧,我如何才能查看我当前库该选项是设置为Yes or No。

    谢谢了

  3. 非常感谢您的回复。
    现在问题解决了,但是具体原因还是不确定,还是很期待您的回复。

    我的解决方法是在Pro*C的.PC文件中加入了
    EXEC ORACLE OPTION(RELEASE_CURSOR=YES);
    参考http://www.cnblogs.com/wintergrass/archive/2011/05/11/2042983.html这篇博文的第9点关于游标的释放。

    但现在问题是这样的,这次项目属于中期升级开发,项目的上一个版本使用的是Oracle10g,当时的Pro*C文件中没有上面我添加的那句话,
    而项目也正常运行,没有受到客户的报错反应。(程序7*24小时运行,服务器正常情况不会重起)

    我想问的就是这个问题点是不是11g的V$OPEN_CURSOR表增加了您说的那个字段而导致的呢?

    还有就是上次的那个问题,在SQL*Plus或者Developer里,
    有没有语句可以常看当前数据库的RELEASE_CURSOR的设置情况,
    或者除了在Pro*C代码中标记出之外,有没有类似于init.ora的配置文件中可以设定这个字段?

    谢谢了,期待您的回复。

    • 你好 据我所知RELEASE_CURSOR是Proc*C Precompiler 编程语言的一种选项, 数据库实例本身是没有该选项的。
      关于该RELEASE_CURSOR 文档Precompiler HOLD_CURSOR and RELEASE_CURSOR Options 给出了较为具体的说明,引用如下:

      
      What are the Oracle Precompiler options HOLD_CURSOR and RELEASE_CURSOR  
      and how do they affect the performance of a PCC program? 
       
      First of all, these options apply to implicit and explicit cursors in 
      all precompiled languages except Pro*Ada.  They apply ONLY to implicit 
      cursors associated with INSERT, UPDATE, DELETE, or a single row SELECT 
      in Pro*Ada.  An explicit cursor in a program is one explicitly created 
      with EXEC SQL DECLARE C1 CURSOR FOR... 
       
      This bulletin discusses what these options do internally and how changing  
      them affects program performance.
      
      HOLD_CURSOR is a precompiler command line parameter.
      
      Summary Operation:
      ~~~~~~~~~~~~~~~~~~
      
      	Statement submitted
      	|
      	Is it in an open cursor?--YES--> EXECUTE  <---.
      	|NO                              ^   ^        |
      	Is HOLD_CURSOR=Y &               |   |        |
      	stmt in HC 'cache'?-----YES------'   |        |
      	|NO                                  |        |
      	Hash it + compare with sql area      |        |
      	|                                    |        |
      	is it in sql area -----YES----(Soft Parse)    |
      	|NO                                           |
      	--------------(Hard Parse)--------------------'
      	
      
      NB:     Both the soft and hard parse register as a parse in tkprof.
              If the cursor is open and it is not in the SQL_AREA then it clearly
              has to parse it (not shown in the diagram!)
      
      
      The HOLD_CURSOR and RELEASE_CURSOR Options 
      ------------------------------------------  
        
      What are the Oracle Precompiler options HOLD_CURSOR and RELEASE_CURSOR 
      and how do they affect the performance of a PCC program? 
       
      First of all, these options apply to implicit and explicit cursors in 
      all precompiled languages except Pro*Ada.  They apply ONLY to implicit 
      cursors associated with INSERT, UPDATE, DELETE, or a single row SELECT 
      in Pro*Ada.  An explicit cursor in a program is one explicitly created  
      with EXEC SQL DECLARE C1 CURSOR FOR... 
       
      Following will be a discussion of what these options do internally and 
      how changing them affects program performance. 
       
      What exactly do we mean by CURSOR?  Unfortunately, we mean two differ- 
      ent things: 
       
          1.  The program cursor - A data structure associated with a SQL 
              statement.  
       
              A program cursor is declared for each SQL statement that the 
              precompiler finds in your program.  For the statements 
        
              EXEC SQL DECLARE SEL_EMP_CURS CURSOR FOR... 
              EXEC SQL INSERT...  
       
              PCC will declare two program cursors, say c1 and c2. 
       
          2.  The Oracle cursor (also called the context area) - The work 
              area created dynamically at run time; this area contains the 
              parsed statement, the addresses of the host variables, and 
              other information necessary to execute the SQL statement.  
       
      These two cursors are linked together via the cursor cache.  The ini- 
      tial size of the cursor cache is determined by the MAXOPENCURSORS op- 
      tion.  
       
      The following diagram illustrates the relationship described above af- 
      ter an insert and an update have been executed in your program: 
        
                                        CURSOR CACHE 
                                     +-----------------+  
      EXEC SQL INSERT...             |   Cache entry   |            Oracle  
      Program cursor P(1)   <---->   |      C(1)       |   <---->   cursor 
                                     +-----------------+  
      EXEC SQL UPDATE...             |   Cache entry   |            Oracle 
      Program cursor P(2)   <---->   |      C(2)       |   <---->   cursor 
                                     +-----------------+ 
          .                          .                 .  
          .                          .                 . 
                                     +-----------------+ 
      EXEC SQL DELETE...             |   Cache entry   | 
      Pgm cursor P(MAXOPENCURSORS)   |P(MAXOPENCURSORS)| 
                                     +-----------------+  
      EXEC SQL SELECT...  
      Pgm cursor P(MAXOPENCURSORS+1) 
        
      etc...  
       
       
      How are the HOLD_CURSOR and RELEASE_CURSOR options related to this 
      view? 
       
      The HOLD_CURSOR option deals with the link between the program cursor 
      and its cache entry. 
       
      The RELEASE_CURSOR option deals with the link between the Oracle cur- 
      sor and the cache entry. 
       
      For SQL statements that are FREQUENTLY RE-EXECUTED, the bottom line is 
      this:  if you want to maximize performance, make sure these SQL state- 
      ments stay "glued" to their respective Oracle cursor. 
       
      What does it mean when a SQL statement is "glued" to its Oracle cur- 
      sor?  It means that both links between the SQL statement and its Ora- 
      cle cursor are made permanent. 
       
      Why would you want to keep a statement "glued" to its context area? 
      Because the context area contains the parsed statement and other in- 
      formation necessary to execute the statement, such as the addresses of 
      the host variables.  Maintaining access to this information makes sub- 
      sequent execution of the statement much faster. 
       
      How do you "glue" a statement to a cache entry?  By correct use of the 
      HOLD_CURSOR and RELEASE_CURSOR options via the PCC command line or in- 
      line with EXEC ORACLE OPTION(...).  
       
      For instance, with HOLD_CURSOR=YES as the Oracle option, a cache entry 
      cannot be flagged for reuse.  This has important implications.  If all 
      cache entries have been used up and a new cache entry is needed for a 
      new SQL statement such that the number of cache entries would now ex- 
      ceed the number specified in MAXOPENCURSORS, Oracle will use the first 
      cache entry marked reuseable. 
        
      For example, in the above diagram, if the cache entry C(1) is marked 
      reusable, and the program is about to execute the EXEC SQL SELECT...  
      (program cursor P(MAXOPENCURSORS+1),  and the number of cache entries 
      in use already equals MAXOPENCURSORS, cache entry C(1) and its Oracle  
      cursor will now be linked to the select statement.  A subsequent exe- 
      cution of the insert statement would require pre-empting a cache entry 
      and its Oracle cursor from another SQL statement and performing a re- 
      parse. 
       
      Correspondingly, with the default RELEASE_CURSOR=NO as the Oracle op- 
      tion, the link between the cache entry and the Oracle cursor (the con- 
      text area) is maintained after the statement is executed so that the 
      parsed statement and, more importantly, the allocated memory stay 
      available. 
       
      The freeing up of this memory by RELEASE_CURSOR=YES means that the 
      next statement that gets linked to this cache entry will require an 
      expensive reallocation of memory in addition to a reparse.  Ugh!  Why 
      would anybody want RELEASE_CURSOR=YES?  We will see later on. 
       
       Program cursor - - - - - [ Cursor cache entry ] - - - - -  Oracle  
      for SQL statement                                           cursor  
                          ^                                ^  
                  HOLD_CURSOR=YES                   RELEASE_CURSOR=NO 
            program cursor is permanently       cache entry maintains the 
              linked to its cache entry.       address of its context area. 
       
      So the HOLD_CURSOR option is intimately tied to the MAXOPENCURSORS op- 
      tion.  What exactly is the MAXOPENCURSORS option?  First of all, MAX- 
      OPENCURSORS is a misnomer.  It should more appropriately be called 
      INITIAL_CURSOR_CACHE_SIZE.  (Okay, so it's a mouthful.)  Anyway, if  
      all cursor cache entries are currently marked "not reusable" either  
      because of the HOLD_CURSOR option or because the associated statement 
      is currently being executed (an explicitly opened cursor is still be- 
      ing fetched on and hasn't been closed yet), then a request for a new 
      cursor will actually result in the extension of the cursor cache at 
      runtime (i.e. if MAXOPENCURSORS=10, and all 10 entries are active, 
      then an 11th will be created).  Just letting the precompiler reuse the 
      oldest cache entry won't always work, as the following example illus- 
      trates:  Imagine the case where the user has ten explicitly declared 
      cursors opened, and wants to execute an eleventh.  If the program ac- 
      tually reuses the oldest program cursor, the user would lose his cur- 
      rent position in the first cursor and would not be able to fetch from 
      it anymore.       
       
      By the way, if an eleventh cache entry is created, when that cursor is 
      closed the eleventh entry is not removed.  Setting MAXOPENCURSORS low 
      saves memory, but causes potentially expensive dynamic allocations of 
      new cache entries if they're needed.  Setting it high assures quick  
      execution, but may use more memory than necessary.  
       
      What if a statement is not executed repeatedly in a program?  Then you 
      could go with the other options HOLD_CURSOR=NO and RELEASE_CURSOR=YES. 
      With the HOLD_CURSOR=NO option, the link between a program cursor and 
      its cache entry is not permanent.  The cache entry is automatically 
      marked reusable in case it is needed.  With the RELEASE_CURSOR=YES op- 
      tion, the Oracle cursor (the context area) is automatically freed and 
      the parsed statement lost.  A reason you might use this option is if 
      you are limited by the number of Oracle cursors (MAXOPENCURSORS) at 
      your site due to memory issues.  You may want to incur the cost of re- 
      allocating memory and reparsing in order to manage memory more effec- 
      tively. 
        
      An advantage of setting RELEASE_CURSOR=YES is that until the link be- 
      tween the cache entry and the Oracle cursor (context area) is removed, 
      ORACLE keeps parse locks on any tables referenced in the SQL state- 
      ment.  These parse locks prevent other users and you from ALTERing or 
      DROPping the tables (does ORA-0057 sound familiar?).  Also, in Version 
      5, it will free up the read-consistent image of the referenced tables 
      stored in ORACLE's Before Image file. 
       
      What do we mean when we say that RELEASE_CURSOR=YES takes precedence 
      over HOLD_CURSOR=YES?  With RELEASE_CURSOR=YES, the link between the 
      Oracle cursor and the cache entry is cut and the Oracle cursor is 
      freed (closed), so even if your program cursor is permanently linked 
      to the cache entry because HOLD_CURSOR=YES, you will still have to re- 
      allocate memory and reparse the statement.  So subsequent executions 
      of a statement don't benefit from the HOLD_CURSOR=YES option because 
      RELEASE_CURSOR=YES. 
       
      For programmers experienced with OCI, here's the OCI equivalent of 
      what's happening: 
       
      #define MAXOPENCURSORS 5 
       
      char     *sql_stmts[10];  
      curs_def cursor[MAXOPENCURSORS]; 
       
      oopen(cursor[0],...); 
      osql3(cursor[0],...,sql_stmts[0],...);  
       
      An example of a "cache entry" being linked to another SQL statement 
      later on in the program is as follows: 
       
      osql3(cursor[0],...,sql_stmts[5],...);  
       
      I am forced to reuse one of my "cache entries" to execute the sixth 
      SQL statement. 
       
      An example of a context area being freed is:  
                       
      oclose(cursor[0]);      
       
      Reusing cursor[0] would require another oopen() and another osql3()-- 
      another dynamic allocation of memory and another reparse. 
       
       
      Conclusion 
      ---------- 
       
      As a programmer, you will get the most from these options by using 
      them selectively inline rather than specifying them as options at pre- 
      compile time.
      
      Reference:
      
      Pro*C/C++ Precompiler Programmer's Guide
      
      
  4. 你好,请问下,我在查询试图v$open_cursor的时候,在现实所有数据的时候,总是在100行以后无法显示其他的数据,一直提示在正在执行中。PL/SQL工具查询或者通过sql plus查询都无法显示.

maclean进行回复 取消回复

*

沪ICP备14014813号-2

沪公网安备 31010802001379号