Sql server 计算列值与其使用的标量函数不同

Sql server 计算列值与其使用的标量函数不同,sql-server,sql-function,calculated-columns,Sql Server,Sql Function,Calculated Columns,我有一个表,其中有一个使用标量函数的计算列 CREATE FUNCTION [dbo].[ConvertToMillimetres] ( @fromUnitOfMeasure int, @value decimal(18,4) ) RETURNS decimal(18,2) WITH SCHEMABINDING AS BEGIN RETURN CASE WHEN @fromUnitOfMeasure=1 THEN @value W

我有一个表,其中有一个使用标量函数的计算列

CREATE FUNCTION [dbo].[ConvertToMillimetres]
(
    @fromUnitOfMeasure int,
    @value decimal(18,4)
)
RETURNS decimal(18,2)
WITH SCHEMABINDING
AS
BEGIN
    RETURN
    CASE 
        WHEN @fromUnitOfMeasure=1 THEN @value
        WHEN @fromUnitOfMeasure=2 THEN @value * 100
        WHEN @fromUnitOfMeasure=3 THEN @value * 1000
        WHEN @fromUnitOfMeasure=4 THEN @value * 25.4
     ELSE @value
    END
END

GO
该表包含此列

[LengthInMm]  AS (CONVERT([decimal](18,2),[dbo].[ConvertToMillimetres]([LengthUnitOfMeasure],[Length]))) PERSISTED,
假设表中的[Length]为62.01249,[LengthUnitOfMeasure]为4,LengthInMm计算值为1575.11,但当我直接运行函数时

SELECT [dbo].[ConvertToMillimetres] (4, 62.01249) GO
它带有1575.12

[长度]列为(十进制(18,4,空))


有人能告诉我为什么会发生这种情况吗?

我不确定这算不算答案,但您可能对特定版本的SQL有问题

我刚刚尝试过复制它(在本地SQL 2014安装上),得到了以下结果:

create table dbo.Widgets (
  Name varchar(20),
  Length decimal(18,4),
  LengthInMm AS [dbo].[ConvertToMillimetres] (4, Length) PERSISTED
)

insert into dbo.Widgets (Name, Length) values ('Thingy', 62.01249)

select * from dbo.Widgets
结果如下:

Name                 Length                                  LengthInMm
-------------------- --------------------------------------- ---------------------------------------
Thingy               62.0125                                 1575.12

(1 row(s) affected)
请注意,您的定义使用了
[LengthInMm]作为(CONVERT([decimal](18,2),[dbo]。[converttomillimeters]([LengthUnitOfMeasure],[Length]))持久化的
,但这似乎对结果没有影响。

我也在我的PC上尝试过(Microsoft SQL Server 2012-11.0.2100.60(X64))。工作正常:

CREATE TABLE dbo.data(
    LengthUnitOfMeasure INT,
    [Length] decimal(18,4),
    [LengthInMm] AS (CONVERT([decimal](18,2),[dbo].[ConvertToMillimetres]([LengthUnitOfMeasure],[Length]))) PERSISTED
)


INSERT INTO dbo.data (LengthUnitOfMeasure, [Length])
SELECT 4, 62.01249

SELECT * 
FROM dbo.data

/*
RESULT
LengthUnitOfMeasure Length  LengthInMm
4                   62.0125 1575.12
*/

我想,我找到了答案:

让我们看看你在说什么:

有一列的数据类型为
decimal(18,4)
。 有一个计算列依赖于此列。 选择计算字段和手动提供相同结果时,结果会有所不同。(对吗?)

对不起,输入参数不一样: 表中的列为
十进制(18,4)
。手动提供的值是十进制(7,5)
(62.01249)

由于表中的列不能存储任何刻度为5的值,因此提供的值将不相等。(此外,
Length
列中的表中没有值为
62.01249
的记录)

从表中查询
[Length]
列时的输出是什么?是不是
62.0124
?如果是,那么这就是答案。由于输入值不相等,因此结果不能相等

更具体一点:
62.01249
将被强制转换(隐式强制转换)为
62.0125

ROUND(25.4 * 62.0124, 2) = 1575.11
ROUND(25.4 * 62.0125, 2) = 1575.12

编辑试图重建模式的每个人都犯了同样的错误(包括我)。当我们(盲目地)将原始问题中的值插入到我们的实例中时,我们将
62.01249
插入到
Length
列->发生了相同的隐式转换,因此我们的表中有值
62.0125

请与我们共享
[Length]
列的数据类型。哦,是的。很抱歉[Length]为(十进制(18,4),null)请运行以下查询(过滤到有问题的记录)并与我们共享结果:从[YourTable]中选择[Length]not true。当我第一次插入表62.01249时,它使62.0125计数。所以当我创建计算列时,它也给出了1575.12。这就是我说的。发生隐式强制转换。我认为OP的db包含一个截断值(6.0124),我们的db包含一个舍入值(62.0125)。OP或其客户端程序在插入期间截断了原始值。他有一个计算列,这意味着他有一个表和一个或多个列来进行计算。他可以检查表中的数值。如果它被截断了,那么他可能会检查客户端程序。如果没有,那么他可以为客户程序的供应商开一张罚单。(如果他在初始加载期间截断了该值,那么他可以做任何他想做的事情)。