【问题标题】:Rounding error with SQL CLR extension (user-defined aggregate)SQL CLR 扩展的舍入错误(用户定义的聚合)
【发布时间】:2011-07-05 05:49:32
【问题描述】:

我正在为 SQL Server 2008 编写一些自定义 .Net 扩展。其中一个是用户定义的聚合,它应该将一组十进制数字聚合为一个十进制值。

为了缩小我的问题范围,我使用了一个简单的 Const 聚合,它只返回一个常量十进制值。将此作为用户定义的聚合添加到 SQL Server 时,返回的值总是四舍五入:

SELECT dbo.Const(n, 2.5) from (select 1 n) x -- returns 3, not 2.5

我错过了什么?

代码如下:

using System;
using System.Data.SqlTypes;
using System.IO;
using Microsoft.SqlServer.Server;
using SqlServer.Clr.Extensions.Aggregates.Implementation;

[Serializable]
[SqlUserDefinedAggregate(Format.UserDefined,MaxByteSize = -1)]
public class Const : IBinarySerialize
{
    private decimal _constValue;

    public void Init() {}

    public void Accumulate(SqlDecimal value, SqlDecimal constValue)
    {
        _constValue = constValue.Value;
    }

    public void Merge(Const value) {}

    public SqlDecimal Terminate()
    {
        return new SqlDecimal(_constValue);
    }

    public void Read(BinaryReader r)
    {
        _constValue = r.ReadDecimal();
    }

    public void Write(BinaryWriter w)
    {
        w.Write(_constValue);
    }
}

将此代码编译为名为@9​​87654324@ 的程序集。以下脚本可用于将其添加到 SQL Server 并验证意外行为:

use [MyDb] -- replace with your db name
go

-- drop the Const aggregate if it exists
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[Const]'))
    DROP AGGREGATE [Const]
GO
-- drop the assembly if it exists
IF  EXISTS (SELECT * FROM sys.assemblies asms WHERE asms.name = N'SqlServer.Clr.Extensions' and is_user_defined = 1)
    DROP ASSEMBLY [SqlServer.Clr.Extensions]
GO

-- import the assembly
CREATE ASSEMBLY [SqlServer.Clr.Extensions]
AUTHORIZATION [dbo]
    FROM 'C:\Path\To\SqlServer.Clr.Extensions.dll'
WITH PERMISSION_SET = SAFE
GO

CREATE AGGREGATE [Const](@input decimal, @constValue decimal)
    RETURNS decimal
    EXTERNAL NAME [SqlServer.Clr.Extensions].[Const] -- put the Const class is in the global namespace
GO

SELECT dbo.Const(n, 2) from (select 1 n) x
SELECT dbo.Const(n, 2.5) from (select 1 n) x

【问题讨论】:

  • 我认为您必须设置小数的精度。尝试在 CREATE AGGREGATE [Const](@input decimal, @constValue decimal) 中将 @constValue decimal 更改为 @constValue decimal(13,2)
  • @Verrigo 哦,我的,当然……也许你应该写下你的评论作为答案,这样我才能接受?

标签: sql-server clr user-defined-aggregate


【解决方案1】:

您必须将@constvalue decimal 更改为@constvalue decimal(13,2)

Create aggregate [const](@input decimal, @constvalue decimal)

【讨论】:

    猜你喜欢
    • 2018-06-07
    • 1970-01-01
    • 2013-07-08
    • 2013-05-25
    • 2010-12-30
    • 1970-01-01
    • 1970-01-01
    • 2021-06-06
    • 2013-12-31
    相关资源
    最近更新 更多