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或其客户端程序在插入期间截断了原始值。他有一个计算列,这意味着他有一个表和一个或多个列来进行计算。他可以检查表中的数值。如果它被截断了,那么他可能会检查客户端程序。如果没有,那么他可以为客户程序的供应商开一张罚单。(如果他在初始加载期间截断了该值,那么他可以做任何他想做的事情)。