“减少”sql十进制数据类型到最低精度和基于值的缩放

时间:2011-06-15 12:13:55

标签: sql casting decimal scale precision

我正在使用相当高的精度处理涉及许多sql十进制乘法的问题。

最近的一个错误促使我做了一些研究,并且我遇到了关于如何计算小数结果的精度和比例的谦卑文章(http://msdn.microsoft.com/en-us/library/ms190476.aspx)。

我的理解是,为了避免截断或意外舍入,有时需要将操作数和可能的中间计算转换为可以工作并给出所需结果的大小。 每个操作数都以十进制给出(19,5)。由于我们支持如此广泛的价值观,所以我无能为力。

我的问题:我可以将这些十进制(19,5)值的类型“即时”减少/转换为最小的十进制类型(精度和比例)值?

例如,我可以将此变量(@Cw)转换为十进制(4,1)'即时',然后才能在我的乘法中使用它吗?

DECLARE @Cw decimal(19,5)
SET @Cw = 113.5

--Some type of CAST, i.e.
--CAST(@Cw as DECIMAL(GetActualPrecision(@Cw), GetActualScale(@Cw)))

-–should show 4 instead of 19
SELECT SQL_VARIANT_PROPERTY(@NewCw, 'Precision') 

–-should show 1 instead of 5
SELECT SQL_VARIANT_PROPERTY(@NewCw, 'Scale')

谢谢!

2 个答案:

答案 0 :(得分:3)

没有

没有动态CAST:比例和精度是静态的:“固定点”
如果你想要arbritrary精度使用float当然是“浮点”

我们大多使用十进制,没有任何问题。

如果您的复杂数学运算效果不佳,那么我会考虑在SQL中使用CLR或在具有更好库的客户端代码中使用CLR

答案 1 :(得分:0)

我遇到了同样的问题,并使用CLR解决了该问题。以下C#函数将十进制类型“打包”到尽可能小的精度和小数位数。

internal static SqlDecimal PackPrecScale(SqlDecimal d)
{
    //Remove leading zeros
    var s = d.ToString();
    var l = s.Length;
    var indexofperiod = s.IndexOf('.');

    //Remove trailing zeros
    if (indexofperiod != -1)
    {
        while (s[l - 1] == '0') l--;
        if (s[l - 1] == '.')
        {
            l--;
            indexofperiod = -1;
        }
    }

    var precision = 6;
    var scale = 0;
    if (l > 0)
    {
        precision = l;
        if (s[0] == '-') precision--;
        if (indexofperiod != -1)
        {
            precision--;
            scale = l - indexofperiod - 1;
        }
        if (precision < 6) precision = 6;
    }

    return SqlDecimal.ConvertToPrecScale(d, precision, scale);
}