Oracle 函数调用的返回值返回 null
Posted
技术标签:
【中文标题】Oracle 函数调用的返回值返回 null【英文标题】:Return value from Oracle function call returns null 【发布时间】:2018-07-18 20:25:56 【问题描述】:我正在尝试从我们的 C# 应用程序调用 Oracle 函数,但它返回 null
而不是数字。
该函数只执行 COUNT(*)
和 RETURNS
只是那个数字。现在,当我尝试从 C# 端调用它时,我总是得到null
的cmd.Parameters["RowCount"].Value
。它不仅仅是null
,而且看起来像一个以null
为值的空对象。
这是从 C# 端看的样子。
OracleCommand cmd = null;
try
cmd = new OracleCommand("pack_Ams_ActivityChange.func_ActivitySearchRowCount", this.Connection);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new OracleParameter("RowCount", OracleDbType.Decimal, ParameterDirection.ReturnValue));
cmd.Parameters.Add(new OracleParameter("FromDate", OracleDbType.Date, DateTime.Now(), ParameterDirection.Input));
cmd.Parameters.Add(new OracleParameter("ThruDate", OracleDbType.Date, DateTime.Now().AddDays(1), ParameterDirection.Input));
int activityRowCount = 0;
cmd.ExecuteNonQuery();
// Errors here since .Value is null
activityRowCount = ((OracleDecimal)cmd.Parameters["RowCount"].Value).ToInt32();
return activityRowCount;
这是函数在数据库中的样子。
FUNCTION func_RowCount
(
in_FromDate IN DATE,
in_ThruDate IN DATE
) RETURN NUMBER AS
lvnCount NUMBER;
lvsSqlStr VARCHAR2(2000);
BEGIN
lvsSqlStr := 'SELECT COUNT(*) FROM SomeTable WHERE StartDate > :in_FromDate AND StartDate < :in_ThruDate';
EXECUTE IMMEDIATE lvsSqlStr INTO lvnCount USING in_FromDate, in_ThruDate;
RETURN lvnCount;
END func_RowCount;
【问题讨论】:
这里的问题出在 C# 端。 oracle 中的 count(*) 至少返回数字 0,并且始终返回数字 >= 0。代码可能只是截取 0 并将其解释为 null,这可能取决于 ODP,但我是很确定就是这样。您可以尝试将其与System.DBNull
进行比较,我敢打赌它们永远不会相等,除非有东西将零作为返回码截获并使其成为null
。
@g00dy 是的,将其与null
甚至DBNull.Value
进行比较得到false
。
现在我们知道它与NULL
不同,我们需要弄清楚是否只有0 值被转换为null
。为此,只需将 pl/sql 函数设为return 1
,然后将其设为return -1
。完成此操作后返回此处并粘贴结果。
【参考方案1】:
我发现 Oracle 数字格式和 .NET 类型转换的奇怪结果和行为 - 特别是在使用没有任何精度的 NUMBER
格式时。我通常将值转换为 OracleDecimal 并使用它构建的 .IsNull
函数,而不是尝试使用 .NET DbNull.Value
等。
var temporaryResult = new OracleDecimal(cmd.Parameters["RowCount"].Value);
activityRowCount = temporaryResult.IsNull ? 0 : Convert.ToInt32(temporaryResult.Value);
仍然不确定为什么它返回 null!
【讨论】:
想想这个,你有没有试过通过元素[0]
而不是名字来访问参数集合?【参考方案2】:
你只需要:
FUNCTION func_RowCount
(
in_FromDate IN DATE,
in_ThruDate IN DATE
) RETURN NUMBER AS
lvnCount NUMBER;
BEGIN
SELECT COUNT(*)
INTO lvnCount
FROM SomeTable
WHERE StartDate > in_FromDate
AND StartDate < in_ThruDate;
RETURN lvnCount;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RETURN 0;
END func_RowCount;
有了这样的例外,即使您的 SELECT 以某种方式返回 null,您也将获得保证数量。完全不需要 EXECUTE 和绑定变量。
此外,由于这是一个函数,您可以将其结果作为通常的选择返回,无需像存储过程那样调用它。 像这样的东西可以解决问题:
cmd = new OracleCommand("select pack_Ams_ActivityChange.func_ActivitySearchRowCount(?,?) from dual", this.Connection);
【讨论】:
计数是否需要 no_data_found 异常? count(*) 即使你的表是空的也会返回 0 你是对的,在这个例子中它不是强制性的。这只是一个好习惯。以上是关于Oracle 函数调用的返回值返回 null的主要内容,如果未能解决你的问题,请参考以下文章
请教:C# WebService调用Java WebService(返回Json类型数据) ,为啥接收为null