【问题标题】:Short circuit in IF clauseIF 子句中的短路
【发布时间】:2012-09-12 15:20:56
【问题描述】:

我已经搜索并没有发现任何相关信息(我认为这是不可能的)。我的问题是我必须检查是否存在临时表,以及该临时表上是否有一些特定数据。

以前有人遇到过这种情况吗?你是如何设法解决的?我想避免创建数百万个 IF..ELSE 块。

编辑:

IF (OBJECT_ID('tempdb..#tempTable') IS NOT NULL 
AND EXISTS (SELECT * FROM #tempTable WHERE THIS_COLUMN = 'value'))
BEGIN
   PRINT 'Temp table and data exists'
END
ELSE
BEGIN
   PRINT 'Temp table or data does not exist'
END

这就是我想做的。当 tempTable 不存在(可能发生)时,问题就来了。它抛出一个错误,因为虽然第一个语句返回 false,但它继续执行第二个语句。并且SELECT 语句无法找到该表,因此会引发错误。我找到的解决方案是这样做:

IF OBJECT_ID('#tempTable') IS NOT NULL
BEGIN
    IF EXISTS (SELECT * FROM #tempTable WHERE THIS_COLUMN = 'value'
    BEGIN
        PRINT 'Temp table and data exists'
    END
    ELSE
    BEGIN
        PRINT 'Temp table exists but data does not exist'
    END
END
ELSE
BEGIN
    PRINT 'Temp table does not exist'
END

我的问题是,有没有办法有 2 个条件,如果第一个条件返回 false,不检查第二个条件?有点像在编程语言中使用&&

【问题讨论】:

  • 百万?从您的描述中听起来像 两个
  • 好吧,我得检查一下临时表是否存在,具体数据是否存在很多次。
  • 独占 AND?这样的事情是不存在的。向我们展示您的一些数据样本以及您需要在那里检查的具体内容。
  • 这里的正确术语是短路而不是排他性和
  • 感谢您的澄清,@Clodoaldo。这正是我想知道的。

标签: sql-server sql-server-2008 bitwise-operators temp-tables


【解决方案1】:

here

不存在 XAND 逻辑门(异与)。从理论上讲,XAND 意味着两个操作数都为真或都为假。所以这意味着 XAND 与等于 (=) 相同,至少对于按位逻辑运算而言。

请显示一些示例代码来说明您要做什么。

问候

【讨论】:

    【解决方案2】:

    我前段时间搜索过这个,如果我没记错的话,Sql Server 确实会短路逻辑条件,但它决定首先检查哪个,而不管它们在if 子句中出现的顺序。

    【讨论】:

    • @MartinSmith 做什么?短路?如果它随机选择其中一个条件,那么它确实选择了一个,并且您无法控制它更改代码中的顺序。
    • 是的,短路。我之前的评论是指向显示此内容的答案的链接。
    • @MartinSmith 好的。现在我看到你对这个主题有一个广泛的答案。
    • 感谢两位的帮助!我认为这应该是可能的,但现在我发现它不是。
    【解决方案3】:

    您尝试做的事情是不可能的,因为这是编译时失败,整个语句需要一起编译。

    它不会评估语句的第一部分,然后仅当它为真时才编译第二部分。您需要将存在性测试和引用表的查询拆分为两个单独的语句,以便分别编译它们。

    【讨论】:

      【解决方案4】:

      我在 MSSQL 中看到了两种接近这一点的方法:

      首先。如果您使用sp_executesql(动态sql),您的存储过程将被编译而不会出错。此外,如果#tempTable 不存在,服务器将输出错误但继续批量执行:

      exec sp_executesql N'SELECT count(*) FROM #tempTable WHERE THIS_COLUMN = ''value'''
      if @@rowcount > 0 
           print 'ok'
      else 
           print 'error'
      end;
      

      第二个。只需创建带有嵌套 IF 和 EXISTS 的用户定义函数(就像您现在所做的那样),输出 0 和 1。并使用动态 sql 输入表名和可能的过滤器值到这个 UDF。在这种情况下,您可以在 IF 中使用此 UDF。

      【讨论】:

      • 这里没有优势。仍然是两种说法。如果该表不存在,则该语句无论如何都要进行延迟编译,因此只有当该语句实际执行时才会出现问题。仅当引用已通过 ALTER TABLE 修改的现有表或执行需要成为批处理中唯一项目的 CREATE 时,您才需要这样做。
      【解决方案5】:

      这可能是一个粗略的解决方案,但我有时会使用 COALESCE 语句来控制您尝试使用的 if、else 和 then 结构。在这种情况下,它看起来有点脏,因为我们正在寻找合并语句的逆。

      DECLARE @temp_message AS varchar(100)
      SELECT @temp_message = COALESCE(CASE
                                       WHEN OBJECT_ID('tempdb..#tempTable') IS NOT NULL THEN NULL
                                       ELSE 'Temp table does not exist'
                                      END,
                                      CASE
                                       WHEN EXISTS (SELECT * FROM #tempTable WHERE THIS_COLUMN = 'value') THEN NULL
                                       ELSE 'Specified value does not exist in temp table'
                                      END,
                                      'Temp table and data exists')
      
      PRINT @temp_message
      

      COALESCE 运行一条又一条语句,直到一条语句不产生 NULL 值。这意味着你可以做一些很酷的事情,比如在运行一个昂贵的大型查询之前运行一系列小查询来检查一些值。让我知道这是否真的是非法的!它在我的机器上工作:)

      【讨论】:

        猜你喜欢
        • 2021-08-20
        • 2017-08-23
        • 2013-02-15
        • 2016-03-26
        • 2011-06-30
        • 2019-10-18
        • 2015-02-13
        • 2013-09-11
        • 2017-02-26
        相关资源
        最近更新 更多