使用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 =之外还有很多功能)。不可否认,它更快,所以它应该适用于相同的数字范围。