sql-server-2008-r2 – 转换SQL Server 2008 R2和2012之间的差异

我在SQL Server 2012中执行SQL语句时遇到了问题,而它在SQL Server 2008 R2中运行完美…

错误消息是:

Msg 8114, Level 16, State 5, Line 1
Error converting data type varchar
to numeric.

我想执行这个SQL Select语句:

Select 
    count(*)
from IMPORTBM 
    inner join ATTRIBUTE on ATT_ATTRIBUTE_ID = IMP_ATTRIBUTE_ID 
where IMP_LOCATION_ID = 2 
    AND IMP_SERIAL_ID = 310001 
    AND IMP_VERSION_ID = 1 
    AND (
        (ATT_ATTRIBUTE = 'PS_APISizing' 
            AND IMP_VALUE = 'C')
        OR
        (ATT_ATTRIBUTE = 'DTD' 
            AND ISNUMERIC(IMP_VALUE) = 1  
            AND  CAST( IMP_VALUE  as NUMERIC(38,19)) <= 0.469) 
        OR
        (ATT_ATTRIBUTE = 'IOD' 
        AND ISNUMERIC(IMP_VALUE) = 1  
        AND  CAST( IMP_VALUE  as NUMERIC(38,19)) BETWEEN 3.684 AND 4.225) 
    )  

你能帮我找出为什么不能使用SQL Server 2012吗?

最佳答案 问题是条件并不总是按照放置它们的顺序进行评估.这意味着如果查询执行计划恰好在IsNumeric(IMP_VALUE)= 1之前对此进行评估,则Cast(IMP_VALUE为数字(38,19))可能会失败,如果它是非数字值.

这不是由有多少条款或您正在运行的SQL Server版本决定的 – 这些只是巧合.问题正如我所描述的那样.使用不同的查询得到不同结果的事实是由于使用不同的执行计划的不同查询或不同的服务器.

解决方法是确保所有条件都不会产生错误,无论它们执行的顺序如何.

对于所有版本的SQL Server,您可以这样做:

Convert(
   numeric(38,19),
   CASE WHEN IsNumeric(IMP_VALUE) = 1 THEN IMP_VALUE ELSE NULL END
) <= 0.469

或者,在SQL Server 2012及更高版本中,您可以使用Try_Convert

Try_Convert(numeric(38,19), IMP_VALUE) <= 0.469

如果您的服务器抱怨这不是内置函数名称,那么很可能您的数据库已从先前版本升级而您需要alter the database compatibility level.请注意,执行此操作可能会在您需要的系统中产生一些其他影响考虑一下,首先要研究它,然后在非生产系统中进行尝试,然后再进行生产(或者在非关键时期进行,并在遇到任何问题时设置兼容性级别).危险不是会发生任何损害,但查询结果可能不同或可能发生错误(查询的不同排序或存储过程结果更常见).

ALTER DATABASE database_name 
SET COMPATIBILITY_LEVEL = 110; -- SQL Server 2012
点赞