Oracle存储过程输出参数值

时间:2017-08-23 00:20:25

标签: c# oracle odp.net

我们的一位客户继承了基于asp.net/oracle的相当大的PMS。不幸的是,我对oracle的了解很少,而且我遇到了一些问题: -

原始系统基于Oracle 9,并使用MS的System.Data.OracleClient驱动程序。新客户选择了Oracle 12c设备盒并且数据库已成功传输,但某些现有存储过程存在问题 - 例如

PROCEDURE IS_PROJECT_LEADER(A_PROJ_ID NUMBER, A_ACCOUNT_ID VARCHAR2, A_SUCCESS OUT VARCHAR2)
IS
    v_COUNT NUMBER;
BEGIN
    --Check if Project Leader, or in the Project Leader Group
    SELECT  COUNT(*)
    INTO    v_COUNT
    FROM    PROJ_ACCOUNT
    WHERE   PROJ_ID = A_PROJ_ID
    AND     ACCOUNT_ID = A_ACCOUNT_ID
    AND     (SYS_ROLE_ID = 3 OR IS_PL_GROUP = 'Y');

    IF v_COUNT > 0 THEN
        A_SUCCESS := 'Y';
    ELSE
        A_SUCCESS := 'N';
    END IF;
END;

使用此代码初始化参数 - 不确定在oracle世界中这是否正确?

while (rdr.Read())
{
  prm = new OracleParameter();
  prm.ParameterName = rdr["ARGUMENT_NAME"].ToString();
  switch (rdr["DATA_TYPE"].ToString())
  {
    case "NUMBER":
      prm.OracleType = OracleType.Number;
      break;
    case "VARCHAR2":
      prm.OracleType = OracleType.VarChar;
      if (rdr["IN_OUT"].ToString() == "OUT"
        || rdr["IN_OUT"].ToString() == "IN/OUT")
      {
        prm.Size = 4000;
      }
      break;
    case "DATE":
      prm.OracleType = OracleType.DateTime;
      break;
    case "BLOB":
      prm.OracleType = OracleType.Blob;
      break;
      case "CLOB":
         prm.OracleType = OracleType.Clob;
         break;

        }
  switch (rdr["IN_OUT"].ToString())
  {
    case "IN":
      prm.Direction = ParameterDirection.Input;
      break;
    case "OUT":
      prm.Direction = ParameterDirection.Output;
      break;
    case "IN/OUT":
      prm.Direction = ParameterDirection.InputOutput;
      break;
  }
  prm.Value = System.DBNull.Value;
  cmd.Parameters.Add(prm);
}

当前系统中A_SUCCESS的返回值始终为空字符串。 如果我删除MS OracleClient并使用最新的Oracle ODP.net驱动程序,则返回所需的字符串值...或者如果我将数据类型和A_SUCCESS的返回类型更改为CHAR,则一切正常。有计划按照MS的建议转移到ODP客户端 - 但系统相当庞大且设计糟糕,因此几个月都没有完成。

我是不是认为这是一个驱动程序问题,而不是我不知道的一些深奥的Oracle功能?

2 个答案:

答案 0 :(得分:0)

我目前在Oracle 12c / c#.Net中工作。我们使用Oracle的ODP驱动程序,我们发现它比Microsoft的驱动程序更成功。

由于评论,我正在改变我说出答案的方式。但我不认为我那么遥远。 MTO给出的线程Exception while executing stored procedure odp.net的接受答案是将varchar2字段的大小或长度添加到参数定义中,这正是我想说的。尽管A_SUCCESS未存储在数据库中,但它需要在该过程中执行存储。

以下是我们所知道的:

  1. 当您将过程数据类型更改为CHAR时,它有效。
  2. 您没有更改c#端的参数(prm)设置,这意味着调用程序使用与VAR相同的VARCHAR2设置。
  3. CHAR的默认长度为1.必须设置VARCHAR2的长度。
  4. 它适用于9i但不适用于12c。 VARCHAR2的存储方式在9i和12c之间变化。
  5. 适用于ODP。如果这是一个长度问题,这很奇怪,因为ODP也需要设置VARCHAR2的长度。
  6. 我试试这个:

    1. 打印每个参数的prm内容,以查看实际设置的内容。
    2. 如果A_SUCCESS未设置为VARCHAR2,请确保它已设置并且设置了长度或大小。
    3. 我知道这是一个很长的镜头,但我会尝试使用局部变量在过程中设置A_SUCCESS的长度。我建议它,因为将数据类型更改为CHAR工作。

答案 1 :(得分:0)

感谢您的帮助。客户决定快速启动转换为ODP,因为它似乎是最合理的解决方案。按预期工作。