【问题标题】:How AND expressions are evaluated?如何评估 AND 表达式?
【发布时间】: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


【解决方案1】:

我认为有一些内部转换(我说的是 SQL 212),因为:

select IIF( 1='a','Found','Missing')

结果

Msg 245, Level 16, State 1, Line 1
Conversion failed when converting the varchar value 'a' to data type int.

和

select IIF(isnumeric('a')=1 and 1='a','Found','Missing')

返回

Missing

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-15
    相关资源
    最近更新 更多