我在SQL Server 2012中执行SQL语句时遇到问题,而它在SQL Server 2008 R2中完美运行...
错误消息是:
Msg 8114,Level 16,State 5,Line 1
转换数据类型varchar时出错 数字。
我想执行此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吗?
答案 0 :(得分:1)
桌子的定义是什么? (至少IMP_VALUE)。为什么不在第一名存储数字... 2008和2012查询计划可能不同,并且不以相同的顺序处理参数和条件。
使用SQL Server 2012(兼容级别110),您可以尝试替换2强制转换:
AND ISNUMERIC(IMP_VALUE) = 1
AND CAST( IMP_VALUE as NUMERIC(38,19)) <= 0.469)
通过
AND TRY_CONVERT(NUMERIC(38,19), IMP_VALUE) <= 0.469
AND TRY_CONVERT(NUMERIC(38,19), IMP_VALUE) BETWEEN 3.684 AND 4.225
当它无法转换时,它返回NULL而没有错误。
答案 1 :(得分:1)
问题是条件并不总是按照放置它们的顺序进行评估。这意味着Cast(IMP_VALUE as numeric(38, 19))
如果是非数字值,如果查询执行计划恰好在IsNumeric(IMP_VALUE) = 1
之前对此进行评估,则会失败。
这不是由你有多少条款或者你正在运行的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