我知道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来克服这个问题。
感谢
答案 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)