将存储为 varchar 的数字 10 与 float 1.1 进行比较失败并出现算术溢出错误

Comparing the number 10 stored as a varchar to a float 1.1 fails with arithmetic overflow error

我正在使用 SQL Server 2008 R2 并且有一个已知问题,即用户将非数字值放入 varchar 列(是的,我知道我可以将其更改为浮点数,但有时不是-numeric 在这个用例中是正确的)。为了处理这个问题,我有一个 SQL 服务器代理作业,它每晚运行并检查列中的值是否可以转换为浮点数,如果不能,则在另一个名为 INRLevelYN 的列中设置一个标志到 1 告诉其他 queries/views 忽略该行。

即使将值 10 从 varchar 列转换为浮点数也有效(并且不设置 inrlevelyn 标志),但在对 inrlevel > 1.1 列进行比较时抛出错误(将 varchar 转换为数据类型 numeric 的算术溢出错误)。

select * 
from VM_AntiCoag_Rosendaal_v2 
where dateofdoseinr between '1/26/2017' and '1/26/2017' 
  and inrlevel > 1.1

如果 inrlevel 列中的值为 10 或更大,这似乎会发生。如果我将值更改为 9.9 或 9,查询 returns 没有错误。

inrlevel 封装为浮点数也解决了这个问题(见下文)

select * 
from VM_AntiCoag_Rosendaal_v2 
where dateofdoseinr between '1/26/2017' and '1/26/2017' 
  and cast(inrlevel as float) > 1.1

我知道 cast as float 解决方案有效,但我想知道这是否是一个已知问题,或者是否有任何其他建议。既然我可以将它转换为浮动,为什么 SQL 服务器在它达到值 10 与 9.9 或 9 时不能正确处理它。

我查看了关于 Whosebug 的建议问题,但我认为他们没有回答这个特定问题,尽管其中一个是三位数范围与两位数范围内的接近寻址号码。

发生这种情况是因为您将 inrlevel 隐式转换为 numeric (2,1),因为这就是 1.1 的比例和精度。和写一样:

select cast(10 as numeric(1,1))

由于您必须显式转换它以避免它,我将它转换为您的号码,而不是列,因此该函数只需调用一次。

select 1 where '10' > cast(1.0 as numeric(4,2))

或者在您的情况下...只需使用适当的精度和比例

select * 
from VM_AntiCoag_Rosendaal_v2 
where dateofdoseinr between '1/26/2017' and '1/26/2017' 
      and inrlevel  > cast(1.1 as numeric(4,2))