【问题标题】:Oracle stored procedure in .net 4.5.net 4.5 中的 Oracle 存储过程
【发布时间】:2012-07-17 13:23:52
【问题描述】:

我正在尝试在 .net 4.5 中执行以下存储过程

 PROCEDURE my_procedure ( 
      a_cursor          OUT t_cursor,
      return_value      OUT VARCHAR2,
      a_type                VARCHAR2,
      a_time                DATE,
      a_id                  VARCHAR2,
      a_arg1                VARCHAR2,
      a_from                VARCHAR2,
      a_gl2                 VARCHAR2,
      a_arg2                DATE DEFAULT NULL,
      a_templ               VARCHAR2 DEFAULT NULL 
      )

这些参数中的大多数可以为空。在 toad 中我可以执行它:

BEGIN package.my_procedure( :c, :out, 'arg', '', '123' , '', '', '', '', ''); END;

在 C# 中,我正在尝试以下操作:

object[] parameters = {
         new OracleParameter("arg1", arg1),
         new OracleParameter("arg", "arg"),
         new OracleParameter("empti", ""),
         new OracleParameter("out", OracleDbType.Varchar2, ParameterDirection.Output),
         new OracleParameter("c", OracleDbType.RefCursor, ParameterDirection.Output)
                                      };

     const string sql = "BEGIN package.my_procedure  
          (:c, :out, :arg, :empti, :arg1 , :empti, :empti, :empti, :empti, :empti); END;";
     res = _projectRepository.ExecuteStoredProcedure(sql, parameters);

我收到以下错误

Test method Tests.repository.RepositoryTests.TestMethod1 threw exception: 
Oracle.DataAccess.Client.OracleException: ORA-06550: 
line 1, column 7:
PLS-00306: wrong number or types of arguments in call to 'my_procedure'ORA-06550: 
line 1, column 7:
PLS-00306: wrong number or types of arguments in call to 'my_procedure'ORA-06550: 
line 1, column 7:
PL/SQL: Statement ignored

我尝试过使用和不使用可选参数以及使用/不使用 return_value/:out 参数。

我正在使用 Oracle.DataAccess 提供程序 v. 4.112.3.0。它适用于没有那么多参数/只有一个输出参数(光标)的其他存储过程。

编辑:我发现一个错误,我需要将输出参​​数放在参数数组中;

new OracleParameter("c", OracleDbType.RefCursor, ParameterDirection.Output),
                    new OracleParameter("out", OracleDbType.Varchar2, ParameterDirection.Output),
                    new OracleParameter("arg1", "arg1"),
                    new OracleParameter("empti", ""),
                    new OracleParameter("arg", arg),
                                      };

现在我得到了错误:

ORA-06502: PL/SQL: numeric or value error: character string buffer too small

看起来像是数据库错误,但看起来很奇怪,因为我可以从 toad 执行相同的命令而不会出现错误。

【问题讨论】:

    标签: oracle .net-4.5 odac


    【解决方案1】:

    当使用VARCHAR2 作为OUPUT 时,您需要提供字符缓冲区的大小。构造函数重载在这里无济于事,您需要手动创建变量以设置所需的属性。

    // Specify a size adequate for the full return value.
    OracleParameter returnValue =
      new OracleParameter("return_value", OracleDbType.Varchar2, 100);
    returnValue.ParameterDirection = ParameterDirection.Output;
    
    object[] parameters = {
      returnValue,
      // other parameters here
    };
    

    原创

    我将保留原始答案,因为它处理了问题的第一个版本。

    提供的错误是正确的,您没有在调用中提供正确数量的参数。让我们看看 Toad for Oracle 可以使用的原始工作代码并将它们映射到参数名称:

    BEGIN
      package.my_procedure(a_cursor     => :c,
                           return_value => :out,
                           a_type       => 'arg',
                           a_time       => '',
                           a_id         => '123',
                           a_arg1       => '',
                           a_from       => '',
                           a_gl2        => '',
                           a_arg2       => '',  -- DEFAULT NULL
                           a_temp1      => ''); -- DEFAULT NULL
    END;
    

    请注意,在 Toad for Oracle 中,您甚至可以为声明为 DEFAULT NULL 的参数提供值(这不是问题)。

    如果您查看参数列表,您会发现您正在为arg1argemptioutp 提供绑定。您将它们定位如下:

    a_cursor     => :c     -- you created the OracleParameter as 'p', not 'c'
    return_value => :out  
    a_type       => :arg
    a_time       => :empti
    a_id         => :arg1
    a_arg1       => :empti
    a_from       => :empti
    a_gl2        => :empti
    a_arg2       => :empti
    a_temp1      => :empti
    

    Oracle 抱怨参数的数量不匹配,这是因为您将引用游标参数声明为p 而不是c。您需要将OracleParamter 更新为c 的名称,或者将第一个参数正在执行的PL/SQL 更改为:p

    【讨论】:

    • 对不起,我编辑了一些参数名称以掩盖代码。在我的原始代码中,它们都是 c/:c。
    【解决方案2】:

    你不需要将输出光标指定为参数

    其他明智的尝试以下代码

    object[] parameters = {
                                              new OracleParameter("arg1", arg1),
                                              new OracleParameter("arg", "arg"),
                                               new OracleParameter("empti", ""),
                                              new OracleParameter("return_value", OracleDbType.Varchar2, ParameterDirection.Output),
                                              new OracleParameter("a_cursor", OracleDbType.RefCursor, ParameterDirection.Output)
                                          };
    
                    const string sql = "BEGIN package.my_procedure(:a_cursor, :return_value, :arg, :empti, :arg1 , :empti, :empti, :empti, :empti, :empti); END;";
                    res = _projectRepository.ExecuteStoredProcedure(sql, parameters);
    

    【讨论】:

    • 没有帮助,首先移动输出参数有帮助。但检查我更新的原始问题,新问题:) :(
    • 为 OUT 参数分配 VARCHAR2 的 MAX 长度。对于输出,C# 分配 0 个字节。
    • 如果您知道输出参数的大小,您可以传递该大小,如果您不知道,那么最大大小就可以让它工作,即使不是最好的。
    猜你喜欢
    • 2014-03-13
    • 2019-08-26
    • 2011-01-03
    • 2011-12-29
    • 2012-03-06
    • 2011-11-03
    • 1970-01-01
    相关资源
    最近更新 更多