与正常情况不同 - 溢出了一个int列。超出最大整数值

时间:2014-08-12 11:09:19

标签: sql sql-server

我知道Int的数据大小限制,但是有这样的错误抛出" varchar值的转换' 51805030400'溢出了一个int列。超出最大整数值。"来自sql server

事情是,抛出错误的行应该用where子句排除。当我运行查询引发错误的策略时,不包括where claus,但是如果我包含where claus则不会。我的问题是,这个政策如何抛出错误,我的印象是在选择之前where claus被执行了。要返回的预期值的最高值是65,126。

在select语句中,我将小数(11,2)转换为Int。

这是代码

     SELECT DISTINCT  
        f.pol_id
        ,   F.trftxn_tot_ordr_amt *100
         ,  CONVERT(int,left(F.trftxn_tot_ordr_amt *100,len(F.trftxn_tot_ordr_amt *100)-3))

       FROM dbo.tr_ftran_header_t F
           INNER JOIN dbo.tr_policy_t  P
                 ON F.pol_id    = P.pol_id


       WHERE 
            (   (F.trftxn_proc_dt > '2014-08-08'
                 AND F.trtxn_stat_cd IN ('PROCESSD', 'REVERSAL')
                )                  
            OR (trftxn_rev_dt > '2014-08-08'
                AND F.trtxn_stat_cd = 'REVERSED')   
             )

为什么它这样执行的任何帮助,我知道我可以改为放入Bigint而不是Int来克服这个问题。

感谢

2 个答案:

答案 0 :(得分:1)

SQL Server重新排列语句处理。无法保证在where中的表达式之前评估select子句。这可能令人困惑。我个人希望错误处理遵循定义的{em>逻辑处理here

不幸的是,您无法使用子查询或CTE解决此问题。 通常解决问题的唯一可靠方法是使用case。我通常会遇到转化问题(try_convert()现在修复了这个问题)。此代码可能会失败:

select cast(col as float)
from t
where isnumeric(col) = 1;

解决方案是:

select (case when isnumeric(col) = 1 then cast(col as float) end)
from t
where isnumeric(col) = 1;

在大多数情况下,case语句 保证处理顺序(使用聚合函数时有一些例外)。

答案 1 :(得分:1)

由于已经stated by Gordon已经无法保证SQL Server中的执行顺序,因此查询优化器可以以其认为最佳的任何方式重写查询执行计划。

在您的情况下,它决定在过滤数据之前转换列,这会导致完全意外的转换错误。不幸的是,它是一个已知的“特性”或SQL Server的错误,现在你需要为它找到一个解决方法。

此问题甚至是raised with Microsoft with a suggestion how to fix it by SQL guru Erland Sommarskog

回到你的代码,如果你正在运行sql server 2012及以上,你可以使用TRY_CONVERT代替简单的CONVERT。如果您使用的是旧版本,则需要使用CASE表达式。

SQL Server 2012及更新版

SELECT DISTINCT  
    ...
    ,TRY_ CONVERT(int,left(F.trftxn_tot_ordr_amt *100,len(F.trftxn_tot_ordr_amt *100)-3))
    ...     

旧版本

SELECT DISTINCT  
    ...
    ,case when <the condition that will ensure a valid conversion> 
        then CONVERT(int,left(F.trftxn_tot_ordr_amt *100,len(F.trftxn_tot_ordr_amt *100)-3))
    end

<强>顺便说一句

您可以直接将DECIMAL转换为INT。 当从DECIMAL(也称为NUMERIC)转换为INT decimals are truncated时。所以例如convert(int,1.25)将导致1 convert(int,1.99)

在您希望结果乘以100的查询中,您可以执行左键 CONVERT(int,F.trftxn_tot_ordr_amt *100)获得与CONVERT(int,left(F.trftxn_tot_ordr_amt *100,len(F.trftxn_tot_ordr_amt *100)-3))

相同的结果

假设F.trftxn_tot_ordr_amt为DECIMAL(11,2)