【问题标题】:Passing Null/empty string to Oracle stored procedure from asp.net从 asp.net 将 Null/空字符串传递给 Oracle 存储过程
【发布时间】:2011-01-22 11:49:20
【问题描述】:

我们有一个 ASP.NET Web 服务,它在我们的 DB (Oracle 11g) 上调用一个存储过程。问题在于,每次将空字符串作为参数之一传递时,对过程的调用都会中断。我们看到 ORA-01084 错误,这表明调用在程序实际运行之前失败。

这是程序,减去一些我认为不相关的逻辑:

PROCEDURE CreateReport
( 
  from_dt IN NVARCHAR2,
  to_dt IN NVARCHAR2,
  p_table_id   IN NVARCHAR2,
  p_column_id  IN NVARCHAR2,
  device_name IN NVARCHAR2,
  ret_cursor OUT t_cursor
)
AS
  v_cursor t_cursor;
  dateStr NVARCHAR2(200);
  sqlStmt VARCHAR2(10000);
  extraColumns NVARCHAR2(10000);
BEGIN

    /* SNIP Cut logic that builds the query statement based on inputs */

    OPEN v_cursor FOR sqlStmt;
    ret_cursor := v_cursor;

END CreateReport;

这是从网络服务调用CreateReport

public DataSet CreateReport(string fromDt, string toDate, string tableNames, 
                            string columnNames, string deviceName)
{
    DataSet dataSet;

    string fmDateStr = String.IsNullOrEmpty(fromDt) ? String.Empty : fromDt.Trim();
    string toDateStr = String.IsNullOrEmpty(toDate) ? String.Empty : toDate.Trim();

    OracleCommand oleDBCmd = new OracleCommand();

    oleDBCmd.CommandType = CommandType.StoredProcedure;
    oleDBCmd.CommandText = "Web_Pkg.CreateReport";

    oleDBCmd.Parameters.Add(new OracleParameter("from_dt", OracleType.NVarChar));
    oleDBCmd.Parameters["from_dt"].Value = fmDateStr;
    oleDBCmd.Parameters["from_dt"].Direction = ParameterDirection.Input;

    oleDBCmd.Parameters.Add(new OracleParameter("to_dt", OracleType.NVarChar));
    oleDBCmd.Parameters["to_dt"].Value = toDateStr;
    oleDBCmd.Parameters["to_dt"].Direction = ParameterDirection.Input;

    oleDBCmd.Parameters.Add(new OracleParameter("p_table_id", OracleType.NVarChar));
    oleDBCmd.Parameters["p_table_id"].Value = tableNames;
    oleDBCmd.Parameters["p_table_id"].Direction = ParameterDirection.Input;

    oleDBCmd.Parameters.Add(new OracleParameter("p_column_id", OracleType.LongVarChar));
    oleDBCmd.Parameters["p_column_id"].Value = columnNames;
    oleDBCmd.Parameters["p_column_id"].Direction = ParameterDirection.Input;

    oleDBCmd.Parameters.Add(new OracleParameter("device_name", OracleType.LongVarChar));
    oleDBCmd.Parameters["device_name"].Value = deviceName;
    oleDBCmd.Parameters["device_name"].Direction = ParameterDirection.Input;


    oleDBCmd.Parameters.Add(new OracleParameter("ret_cursor", OracleType.Cursor));
    oleDBCmd.Parameters["ret_cursor"].Direction = ParameterDirection.Output;

    try
    {
        // Throws exception if any of the paramters are String.Emtpy
        dataSet = DB.SQLSelect(oleDBCmd, connStr);
    }
    catch (Exception exp)
    {
        return null;
    }
    finally
    {
        if (oleDBCmd != null)
        {
            oleDBCmd.Dispose();
        }
    }

    return dataSet;
}

作为实验,我修改了 Web 服务以传递 null 而不是空字符串。传入 null 时,我看到一个错误,指出“调用 'CREATEREPORT 的参数数量或类型错误。”

我也尝试在参数为空/空时传递DBNull.Value,但这会导致错误

Parameter 'p_column_id': No size set for variable length data type: String.

(当然,在这种情况下,p_column_id 是空参数)。

那么,我怎样才能成功地将空字符串作为参数传递给我的存储过程呢?我们肯定想让 p_column_id 参数为空。

【问题讨论】:

    标签: asp.net oracle stored-procedures null dbnull


    【解决方案1】:

    您可以对任何可为空的参数执行以下操作。

    oleDBCmd.Parameters.Add(new OracleParameter("to_dt", OracleType.NVarChar));
    if(string.IsNullOrEmpty(toDateStr)) {
        oleDBCmd.Parameters["to_dt"].Value = DBNull.Value;
    } else {
        oleDBCmd.Parameters["to_dt"].Value = toDateStr;
    }
    oleDBCmd.Parameters["to_dt"].Direction = ParameterDirection.Input;
    

    这样,您不依赖于 oracle 适配器的字符串 -> 空转换。

    编辑:如果这不能解决问题,很可能是类型之间的不匹配,检查 NVarChar 与 VarChar

    【讨论】:

    • 确实是类型不匹配。 device_name 和 p_column_id 参数在 Web 服务中使用了不正确的类型。它们是 OracleType.LongVarChar,但它们应该是 OracleType.NVarChar。谢谢!
    猜你喜欢
    • 2012-03-30
    • 2013-10-24
    • 2014-04-16
    • 2017-03-21
    • 1970-01-01
    • 2012-04-16
    • 1970-01-01
    • 1970-01-01
    • 2013-06-13
    相关资源
    最近更新 更多