【问题标题】:Subquery in ISNULL,IIF,CASE statementsISNULL,IIF,CASE 语句中的子查询
【发布时间】:2015-08-21 14:29:07
【问题描述】:

在 ISNULL 或 IIF 或 CASE 中作为参数给出的子查询将在不考虑条件的情况下执行

为了解释我的意思,请考虑以下示例。当我运行以下查询并查看执行计划时,我发现即使变量 @Id 不是 NULL,第二个条件也会始终执行。

谁能解释一下为什么子查询会在查询 1、2、3 中执行?

--Create a Temp table
IF OBJECT_ID('tempdb..#TempTable') IS NOT NULL DROP TABLE #TempTable
CREATE TABLE #TempTable
(
ID INT
)

--Insert some data
INSERT INTO #TempTable VALUES(1),(2),(3),(4),(5),(6),(7),(8),(9),(10)

DECLARE @Id INT = 1

--Query 1: ISNULL
SET @Id= ISNULL(@Id, (SELECT TOP 1 ID FROM #TempTable TT WHERE TT.ID = 1))
SELECT @Id AS ID

--Query 2: IIF
SET @Id=  IIF(@Id IS NULL,(SELECT TOP 1 ID FROM #TempTable TT WHERE TT.ID = 1),@Id)
SET @Id=  IIF(@Id IS NOT NULL,@Id,(SELECT TOP 1 ID FROM #TempTable TT WHERE TT.ID = 1))

SELECT @Id AS ID

--Query 3: CASE
SET @Id=  CASE WHEN @Id IS NULL THEN (SELECT TOP 1 ID FROM #TempTable TT WHERE TT.ID = 1) ELSE @Id END
SET @Id=  CASE WHEN @Id IS NOT NULL THEN @Id ELSE (SELECT TOP 1 ID FROM #TempTable TT WHERE TT.ID = 1)  END
SELECT @Id AS ID

---Query 4: IF
IF @Id IS NULL
BEGIN
    SET @Id = (SELECT TOP 1 ID FROM #TempTable TT WHERE TT.ID = 1) 
    SELECT @Id AS ID
END
ELSE 
BEGIN
    SELECT @Id AS ID
END

【问题讨论】:

  • 您的查询在这里充满了逻辑错误。您到处都有顶部,但没有一个订单。除非您指定订单,否则您无法确保将返回哪一行……当然,在这种情况下,由于 where 子句,它只能是一行。是的,执行计划必须确定它如何运行。计划不以数据为条件,它必须针对任何条件制定计划。
  • 简单的答案是 SQL Server 不像其他编程语言(c#、vb)等那样进行短路。
  • @SeanLange 这只是我想出的一个非常小的例子......当然还有一个 WHERE 子句。我认为这些名称具有误导性,许多人可能不会想到这种行为,我想大多数人甚至不会像这样简单查询查询计划,我只是幸运地注意到了这一点。

标签: sql sql-server subquery isnull iif


【解决方案1】:

如果您希望子查询仅在满足 null 条件时执行,请使用 IF 而不是 ISNULL

if @Id is null
   set @id = (SELECT TOP 1 ID FROM #TempTable TT WHERE TT.ID = 1)

而不是

SET @Id= ISNULL(@Id, (SELECT TOP 1 ID FROM #TempTable TT WHERE TT.ID = 1))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多