2

使用 SqlDecimals 时,我得到了一些意想不到的结果。最后,在划分 2 个 SqlDecimal 时,它似乎归结为规模问题。

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)小数,因此不能将信息塞进它的 3 个字节中?!?!?

PS:我无法预测数字(p,s)的哪些组合将传递给函数,但 38,8 是“可接受的”。我希望为我的原始 UDF 制作一个更快的 SQLCLR 版本(它所做的不仅仅是除法 =)。诚然,它更快,但它应该适用于相同的数字范围。

4

0 回答 0