【发布时间】:2013-11-20 11:17:52
【问题描述】:
我有以下情况:
DECLARE @DataSource TABLE
(
[ID] BIGINT
)
INSERT INTO @DataSource ([ID])
VALUES (1)
,(2)
,(3)
DECLARE @IDForSearch VARCHAR(4) = 'TEXT'
如果我们尝试使用错误的类型参数提取记录:
SELECT IIF( EXISTS( SELECT 1 FROM @DataSource WHERE [ID] = @IDForSearch), 'Found', 'Missing')
我们收到以下错误:
Msg 8114, Level 16, State 5, Line 14
Error converting data type varchar to bigint.
但如果我添加一个简单的 isNumeric 检查一切是否正常:
SELECT IIF( ISNUMERIC(@IDForSearch) = 1 AND EXISTS( SELECT 1 FROM @DataSource WHERE [ID] = @IDForSearch), 'Found', 'Missing')
我首先想到的是表达式的第一部分被执行了:
ISNUMERIC(@IDForSearch) = 1
因为它失败了,所以第二个没有执行,也没有抛出错误。
但是,如果我更改表达式位置,一切都会再次正常工作:
SELECT IIF( EXISTS( SELECT 1 FROM @DataSource WHERE [ID] = @IDForSearch) AND ISNUMERIC(@IDForSearch) = 1, 'Found', 'Missing')
为什么在这些情况下没有错误?
【问题讨论】:
-
我认为这不是基于您编写它的顺序(如您所示)。数据库引擎(顺便说一句,您尚未指定您使用的是哪一个)可以选择它喜欢的顺序,并且它可能决定
IsNumeric()的成本低于select。我的意思是查询优化器将根据成本决定使用哪个顺序。 -
并补充 acfrancis 所说的,几乎任何可能导致引擎在未来某个时间点改变其决定 - 服务器的任何补丁,更改为索引等。不幸的是,没有办法强制它以特定顺序评估
WHERE子句。 -
@Damien_The_Unbeliever 这正是我所担心的。我将拆分表达式以避免将来出现问题。
-
公平地说,我认为隐式转换只是因为变量设置为'TEXT'而失败。有很多方法可以防止这种情况发生。
-
我认为这是不正确的。请参阅下面的答案。我不使用“TEXT”
标签: tsql sql-server-2012 exists logical-operators iif