如何调用返回引用游标的Oracle存储过程

Posted

技术标签:

【中文标题】如何调用返回引用游标的Oracle存储过程【英文标题】:How to call Oracle stored procedure which returns ref cursor 【发布时间】:2013-10-18 04:00:52 【问题描述】:

我正在尝试调用返回 ref 游标的 Oracle 存储过程,并且我需要从返回的数据生成树视图。我是新手,我有两个问题。

第一个问题是我无法调用该程序。我收到此错误:“调用 'OBJECT_HIERARCHY' 时​​参数的数量或类型错误”

我的第二个问题是我不明白当这个过程返回一个引用游标值时我将如何获取该数据?该表中有超过 5000 条记录,我没有得到该数据,而是一个参考游标值。有人可以解释我如何使用参考光标值获取该数据。我没有使用 Oracle 的经验。

这是oracle中的过程定义:

CREATE OR REPLACE PROCEDURE SAD.object_hierarchy  
(nAppId IN NUMBER,
nParentId IN NUMBER DEFAULT -1, 
o_cRefCursor OUT SYS_REFCURSOR)
IS
BEGIN
IF NOT o_cRefCursor%ISOPEN THEN

  OPEN o_cRefCursor FOR 
     SELECT
        h.PARENT_ID, h.CHILD_ID, h.H_LEVEL,
        o.OBJECT_IDENTIFIER, o.OBJECT_TYPE_ID
     FROM
     (
        SELECT
           PARENT_ID, CHILD_ID, LEVEL AS H_LEVEL
        FROM OBJECT_RELATIONSHIPS
        START WITH PARENT_ID = nParentId --> -1 --= 60170
        CONNECT BY PRIOR CHILD_ID = PARENT_ID
     ) h
     INNER JOIN
        OBJECTS o
        ON
           o.OBJECT_ID = h.CHILD_ID AND
           O.APPLICATION_ID = nAppId;   
 END IF;
END object_hierarchy;

这些是表字段定义

Column Name               Data Type            

 OBJECT_REL_ID            NUMBER (14)                    
 PARENT_ID                NUMBER (14)                    
 CHILD_ID                 NUMBER (14)                    
 OBJECT_IDENTIFIER        VARCHAR2 (255 Byte)    
 OBJECT_TYPE_ID           VARCHAR2 (5 Byte)

这是我返回错误的代码:

            string oradb = "Data Source=(DESCRIPTION="
         + "(ADDRESS=(PROTOCOL=TCP)(HOST=tnt33)(PORT=1521))"
         + "(CONNECT_DATA=(SERVICE_NAME=ORCL)));"
         + "User Id=xxx;Password=xxxxx;";
        OracleConnection con = new OracleConnection(oradb);

        try
        
            con.Open();
            OracleCommand cmd = new OracleCommand();
            cmd.Connection = con;
            cmd.CommandType = System.Data.CommandType.StoredProcedure;
            cmd.CommandText = "SAD.object_hierarchy";
            cmd.Parameters.Add("nAppId", OracleDbType.Int16).Value = 1;
            OracleParameter oraP = new OracleParameter();
            oraP.OracleDbType = OracleDbType.RefCursor;
            oraP.Direction = System.Data.ParameterDirection.Output;
            cmd.Parameters.Add(oraP);
            OracleDataReader reader = cmd.ExecuteReader();

            while (reader.Read())
            

            
            reader.Close();    
        
        catch (Exception ex)
        

            con.Close();
        

有人可以帮我解释一下为什么我的代码会返回此错误:“调用 'OBJECT_HIERARCHY' 时​​参数的数量或类型错误”

【问题讨论】:

【参考方案1】:

例子:

string connStr = "Data Source=...";
DataSet dataset = new DataSet();

string connStr = ConfigurationManager.ConnectionStrings["OracleConn"].ToString();

using (OracleConnection objConn = new OracleConnection(connStr))

    OracleCommand cmd = new OracleCommand();
    cmd.Connection = objConn;
    cmd.CommandText = "Oracle_PkrName.Stored_Proc_Name";
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.Parameters.Add("Emp_id", OracleType.Int32).Value = 3; // Input id
    cmd.Parameters.Add("Emp_out", OracleType.Cursor).Direction = ParameterDirection.Output;

    try
    
        objConn.Open();
        cmd.ExecuteNonQuery();
        OracleDataAdapter da = new OracleDataAdapter(cmd);
        da.Fill(dataset);                   
    
    catch (Exception ex)
    
        System.Console.WriteLine("Exception: 0", ex.ToString());
    
    objConn.Close();

【讨论】:

对于使用 OracleManagedDataAccess 的最新版本,必须使用 OracleDbType.RefCursor 而不是 OracleType.Cursor @ΩmegaMan:当我将 OracleDbType.RefCursor 的方向更改为 ReturnValue 而不是 Output 时,我得到一个异常“错误的数字或类型或参数”......这是为什么? @Nina 将输出光标的顺序从现在的位置更改为第一个或最后一个位置。我在使用它时不得不玩弄它。 @ΩmegaMan:我将光标参数的顺序(在我的情况下是返回值)更改为第一个,现在它可以工作了。谢谢【参考方案2】:

如果您要提供OUT,则还需要提供nParentId,因为.NET 在将语句发送到服务器时不会命名这些参数。

cmd.Parameters.Add("nParentId", OracleDbType.Int16).Value = -1;

【讨论】:

终于成功了。谢谢你。我编辑了我的第一篇文章以更正代码 我已经回滚了对您帖子的编辑,因为我正在阅读您的问题并且无法弄清楚出了什么问题。让问题保持原样。

以上是关于如何调用返回引用游标的Oracle存储过程的主要内容,如果未能解决你的问题,请参考以下文章

oracle存储过程返回游标,取值报错

Oracle 存储过程调用返回游标的另一个存储过程。

Oracle PL SQL:比较两个存储过程返回的引用游标结果

MySql数据库的存储过程能返回游标么?

PL/SQL 打印出存储过程返回的引用游标

Oracle调用存储过程返回游标结果