代码之家  ›  专栏  ›  技术社区  ›  Conrad Frix

执行在C中返回引用游标的oracle函数#

  •  10
  • Conrad Frix  · 技术社区  · 15 年前

    我有一个oracle包,它的过程有一个in-out引用游标。我的理解是这是相当标准的。

    So I asked this question 结果是,我可以通过创建一个包装过程的函数来得到我想要的。

    看起来我不再需要这个函数了,但是对于那些好奇的人来说,看看原始的问答更新还是值得知道的。

    这是函数

    FUNCTION GetQuestionsForPrint (user in varchar2)
      RETURN MYPACKAGE.refcur_question
    AS  
    
        OUTPUT MYPACKAGE.refcur_question;
    
    BEGIN 
    
          MYPACKAGE.GETQUESTIONS(p_OUTPUT => OUTPUT, 
          p_USER=> USER ) ;
    
    
      RETURN OUTPUT;
    END;
    

    下面是我在sqldeveloper中执行它的步骤

    var r refcursor;
    exec :r := mypackage.getquestionsForPrint('OMG Ponies');
    print r;
    

    所以从现在开始,我可能会把ForPrint函数添加到我的所有过程中。

    为了测试这一点,我试着从.NET执行这个函数,但我做不到。真的是这样吗。

    using (OracleConnection cnn = new OracleConnection("Data Source=Test;User Id=Test;Password=Test;"))
    {
        cnn.Open();
        OracleCommand cmd = new OracleCommand("mypackage.getquestionsForPrint");
        cmd.CommandType = System.Data.CommandType.StoredProcedure;
    
        cmd.Parameters.Add ( "p_USER", "OMG Ponies");
    
        cmd.Connection = cnn;
        OracleDataReader rdr = cmd.ExecuteReader();
    
        while (rdr.Read())
        {
            Console.WriteLine(rdr.GetOracleValue(0));
        }
    
        Console.ReadLine();
    }
    

    所以我得到了错误。

    getquestionsForPrint is not a procedure or is undefined

    我也试过ExecuteScalar,结果也一样。

    编辑 根据Slider345的建议,我还尝试将命令类型设置为text,并使用以下语句 无效的SQL语句

    mypackage.getquestionsForPrint('OMG Poinies');
    

    var r refcursor; exec :r :=  mypackage.getquestionsForPrint('OMG Poinies'); 
    

    select mypackage.getquestionsForPrint('OMG Poinies') from dual
    

    “0x61c4aca5”处的指令 内存无法“读取”。

    尝试添加输出参数没有帮助。

    cmd.Parameters.Add(null, OracleDbType.RefCursor, ParameterDirection.Output);
    

    不知道是怎么回事 名称应为

    ORA-06550:第1行,第7列: PLS-00306:错误数量或类型的 调用中的参数 '获取问题提示'

    最终编辑(希望如此)

    similar question 三个月后我做了。他得到的答案是

    • 将命令文本设置为匿名块
    • 将参数绑定到ref游标,设置输出方向

    using (OracleConnection cnn = new OracleConnection("Data Source=Test;User Id=Test;Password=Test;"))
    {
        cnn.Open();
        OracleCommand cmd = new OracleCommand("mypackage.getquestionsForPrint");
        cmd.CommandType = CommandType.Text;
    
        cmd.CommandText = "begin " +
                  "    :refcursor1 := mypackage.getquestionsForPrint('OMG Ponies') ;"  +
                  "end;";
    
        cmd.Connection = cnn;
        OracleDataAdapter da = new OracleDataAdapter(cmd);
        cmd.ExecuteNonQuery();
    
        Oracle.DataAccess.Types.OracleRefCursor t = (Oracle.DataAccess.Types.OracleRefCursor)cmd.Parameters[0].Value;
        OracleDataReader rdr = t.GetDataReader();
        while(rdr.Read())
            Console.WriteLine(rdr.GetOracleValue(0));
    
        Console.ReadLine();
    }
    
    4 回复  |  直到 8 年前
        1
  •  5
  •   Peter C    14 年前

    我没有用函数来测试它,而是针对我的存储过程。我为refCursor指定out参数。

    command.Parameters.Add(new OracleParameter("refcur_questions", OracleDbType.RefCursor, ParameterDirection.Output));
    

    ParameterDirection.ReturnValue
    

    我正在使用Oracle.DataAccess版本2.111.6.0

        2
  •  3
  •   th1rdey3    6 年前

    我不得不在问题和答案之间上下移动,以找出有效的完整代码。所以我在这里给出了对我和其他人有用的完整代码-

    var sql = @"BEGIN :refcursor1 := mypackage.myfunction(:param1) ; end;";
    using(OracleConnection con = new OracleConnection("<connection string>"))
    using(OracleCommand com = new OracleCommand())
    {
         com.Connection = con;
         con.Open();
         com.Parameters.Add(":refcursor1", OracleDbType.RefCursor, ParameterDirection.Output);
         com.Parameters.Add(":param1", "param");
         com.CommandText = sql;
         com.CommandType = CommandType.Text;
         com.ExecuteNonQuery();
         OracleRefCursor curr = (OracleRefCursor)com.Parameters[0].Value;
         using(OracleDataReader dr = curr.GetDataReader())
         {
             if(dr.Read())
             {
                 var value1 = dr.GetString(0);
                 var value2 = dr.GetString(1);
             }
         }
     }
    

    希望有帮助。

        3
  •  0
  •   user1203443 user1203443    12 年前

    我知道这是一篇很老的帖子,但由于我花了很长时间才弄清楚让.NET与Oracle“和睦相处”所涉及的所有细节,我想我应该把这条建议放在这个棘手的情况下给其他人。

    我经常调用在我们的环境中返回REF\游标的Oracle存储过程(.net3.5对oracle11g)。对于一个函数,您确实可以随意命名参数,但是您需要设置它的名称 System.Data.ParameterDirection = ParameterDirection.ReturnValue ExecuteNonQuery OracleCommand OracleDataReader OracleDataReader .

    我会发布完整的代码,但是我用VB.NET版几年前,数据访问层(我们的企业内部网)的大部分代码都是用C语言编写的。我认为在一个单独的回答中混合语言会是更大的失礼。