TSQL Round()函数不能以相同的方式工作两次

时间:2015-04-13 14:56:44

标签: sql-server tsql

我无法使用相同的逻辑使Round()函数正常运行。

代码:

Declare @Cycle AS INT;
SELECT @Cycle = CycleTime 
FROM MachineStatus 
WHERE MachineNumber = @MN;

UPDATE Job_Op_Time
SET Act_Run_Qty = Act_Run_Qty + 1, Act_Run_Hrs = ROUND(CAST(((Act_Run_Qty + 1) * @Cycle) AS FLOAT)/3600,2),
Act_Run_Labor_Hrs = ROUND(CAST(((Act_Run_Qty + 1) * @Cycle) AS FLOAT)/3600,2)
WHERE Job_Operation = @Op AND Work_Date = DATEADD(dd,0,DATEDIFF(dd,0,@L))

计算Act_Run_Hrs和Act_Run_Labor_Hrs的上述行应该给出相同的结果,但它们不会(它们是相同的代码!)。例如,Act_Run_Hrs将设置为6,Act_Run_Labor_Hrs将设置为6.96。

由于

编辑:如果重要,这是代码在插入后触发器

3 个答案:

答案 0 :(得分:1)

你还应该看一下MSDN上的round函数,它有第三个可选参数function,默认情况下是0执行舍入但是当0之外的任何值在指定值之后截断结果时

ROUND ( numeric_expression , length [ ,function ] )

你为什么要使用浮动?任何具体原因。 FLOAT是你的罪魁祸首

但是,转换为float时,我的问题是CAST操作。浮动是approximate numeric data type这并不能保证每次返回的值都相同。

修改

MSDN says

IEEE 754规范提供了四种舍入模式:舍入到最近,向上舍入,向下舍入和舍入到零。 Microsoft SQL Server使用向上搜索。所有都精确到保证精度,但可能导致浮点值略有不同。因为浮点数的二进制表示可能使用许多合法舍入方案中的一种,所以不可能可靠地量化浮点值。

答案 1 :(得分:0)

SQL Server有一个确定性概念,这意味着给定相同的输入,您总能得到相同的结果。在确定性函数的列表(https://technet.microsoft.com/en-us/library/aa214775%28v=sql.80%29.aspx)上,SQL Server包含round函数。如果它不像宣传的那样工作(圆形是非常广泛使用并且已经永远存在)相信我这已经被发现了。

这是一种几乎可以肯定是不同输入或设置的情况。由于它在触发器中你的更改/插入在表'插入'中我将使用inserted和output子句的组合来查看输入到round函数的确切内容以及输出是什么。它不是你的想法。

答案 2 :(得分:0)

您所建议的内容并没有多大意义,因此查询之外必定存在导致此问题的内容。

我的猜测是列的类型是:

  • Act_Run_Hrs整数
  • Act_Run_Labor_Hrs float

在这种情况下,对于Act_Run_Hrs,sql sever会从float到整数进行隐式转换(如下所示),这样可以得到你看到的结果。

UPDATE 
    Job_Op_Time
SET 
    Act_Run_Qty =       Act_Run_Qty + 1, 
    Act_Run_Hrs =       CAST(ROUND(CAST(((Act_Run_Qty + 1) * @Cycle) AS FLOAT)/3600,2) as int),
    Act_Run_Labor_Hrs = ROUND(CAST(((Act_Run_Qty + 1) * @Cycle) AS FLOAT)/3600,2)
WHERE 
    Job_Operation = @Op 
    AND Work_Date = DATEADD(dd,0,DATEDIFF(dd,0,@L))

另一种可能性是另一个交易正在进入并更改此更新运行与您查看结果之间的数据。