1

我有以下语句在一个非常大的存储过程结束时执行。

UPDATE myTable
SET    DiffPerc = CAST(CASE
                         WHEN ( CASE
                                  WHEN SimExt = 0
                                       AND StdExt = 0 THEN 0
                                  WHEN StdExt = 0 THEN 99999
                                  ELSE SimExt - StdExt / StdExt
                                END ) * 100 > 99999 THEN 99999
                         ELSE ( CASE
                                  WHEN SimExt = 0
                                       AND StdExt = 0 THEN 0
                                  WHEN StdExt = 0 THEN 99999
                                  ELSE SimExt - StdExt / StdExt
                                END ) * 100
                       END AS DECIMAL(8, 2)) 

这个想法是我有一个字段来确定一个值与另一个值的百分比差异。该字段是toDiffPerc的百分比差异。这个例程每天都有效,已经一年多了,但是,从两天前开始,我开始收到以下错误消息:SimExtStdExt

将数字转换为数字数据类型的算术溢出错误。

我理解这条消息的含义,但嵌入 case 语句的全部意义在于测试分母中的 0,以及在将值打包到DECIMAL (8, 2)字段中之前检查任何非常高的值百分比。

我错过了什么?如何更新此语句以解决所有可能的边缘情况并在溢出发生之前处理它?

另外,请注意,99999以百分比形式的硬编码值是向最终用户表明有人搞砸了的标志。

4

4 回答 4

1

也许这是一个错字,但在我看来,您缺少一组括号。

IE

(SimExt - StdExt) / StdExt否则你总是会这样做,SimExt - 1因为减法是在除法之后完成的。

注意区别:

select CAST((99999999 - 99999998) / 99999998 as decimal(8,2))
select CAST(99999999 - 99999998 / 99999998 as decimal(8,2))
于 2012-08-20T09:30:15.667 回答
0

最终结果超过大小 (8,2)。你需要增加规模

于 2012-08-17T13:58:04.953 回答
0

这可能是一个超出范围的高值。尝试更改为

  (CASE  
   WHEN SimExt = 0 AND StdExt = 0 THEN 0  
   WHEN StdExt = 0 THEN 99999  
   when simext>1000000 then null
   ELSE SimExt - StdExt / StdExt  
   END) * 100 > 99999 
于 2012-08-17T14:00:15.077 回答
0

SQL 不做短路评估,所以你必须保护它。 http://en.wikipedia.org/wiki/Short-circuit_evaluation

实际上,它将评估这两种情况并最终选择正确的路径。

于 2012-08-17T14:11:06.977 回答