SQLCLR项目中的SqlDecimal问题

时间:2012-06-20 09:54:00

标签: c# sql-server precision sqlclr overflowexception

使用SqlDecimals时,我遇到了一些意想不到的结果。最后,当划分2个SqlDecimals时,似乎可以归结为缩放问题。

c#示例代码如下所示:

[Microsoft.SqlServer.Server.SqlFunction]
[return: SqlFacet(Precision = 38, Scale = 8)]
public static SqlDecimal fn_divide([SqlFacet(Precision = 38, Scale = 8)]SqlDecimal x, [SqlFacet(Precision = 38, Scale = 8)]SqlDecimal y)
{
    var r = SqlDecimal.Divide(@x, @y);

    return r;
}

SQL测试代码如下所示:

DECLARE @x numeric(38, 8),
        @y numeric(38, 8)

SELECT @x = Replicate('1', 28) + '.12345678',
       @y = '0.25896314'

SELECT via = 'TSQL', x = @x, y = @y, r = Convert(numeric(38, 8),  @x / @y)
SELECT via = 'SQLCLR', x = @x, y = @y, r = dbo.fn_divide(@x, @y)

第二个选择返回以下错误:

A .NET Framework error occurred during execution of user-defined routine or aggregate "fn_divide": `
System.OverflowException: Arithmetic Overflow.
System.OverflowException: 
   at System.Data.SqlTypes.SqlDecimal.MultByULong(UInt32 uiMultiplier)
   at System.Data.SqlTypes.SqlDecimal.AdjustScale(Int32 digits, Boolean fRound)
   at System.Data.SqlTypes.SqlDecimal.op_Division(SqlDecimal x, SqlDecimal y)
   at System.Data.SqlTypes.SqlDecimal.Divide(SqlDecimal x, SqlDecimal y)
  at UserDefinedFunctions.fn_divide(SqlDecimal x, SqlDecimal y)

搜索网络我发现在将SqlDecimal转换为Decimal时出现了与舍入错误相关的大量问题,但在我的情况下,从头到尾一切都是SqlDecimal,因为我想避免这种情况。 同样地,我希望结果与在SQL中原生实现的结果相同......但是唉。即使它没有溢出,它也会在“边界情况”中给出不同的结果。

任何人都有关于如何解决此问题或至少解决此问题的任何提示? SqlDecimal内部是否使用(.Net)Decimals,因此无法将信息填入其中3个字节?!?!?

PS:我无法预测数字(p,s)的哪些组合将传递给函数,但38,8是“可接受的”。我希望能够制作一个更快的SQLCLR版本的原始UDF(它除了分割btw =之外还有很多功能)。不可否认,它更快,所以它应该适用于相同的数字范围。

0 个答案:

没有答案