如何将SQL短路的短路

时间:2013-10-17 14:17:34

标签: sql sql-server tsql

我正在尝试在SQL server中执行以下查询:

declare @queryWord as nvarchar(20) = 'asdas'

SELECT  * FROM TABLE_1 
WHERE (ISDATE(@queryWord) = 1) 
AND TABLE_1.INIT_DATE = CONVERT(Date, @queryWord)

这显然会导致错误,因为'asdas'无法转换为Date。虽然,我期待一种不同的行为。也就是说,因为ISDATE(@queryWord) = 1是假的,我期待SQL不检查第二个条件,但显然,它确实如此。

我知道还有其他一些方法可以执行此查询,但这不是我的问题。我想知道是否有一些方法不检查第二个条件是第一个不满足。我很好奇,因为我认为SQL已经做到了。

5 个答案:

答案 0 :(得分:11)

SQL Server不会做短路(也不应该)。

如果您在某些情况下需要尝试某些内容,则需要以编写查询的方式强制执行此操作。

对于此查询,最简单的解决方法是在CASE子句中使用WHERE表达式。

declare @queryWord as nvarchar(20) = 'asdas'

SELECT  * FROM TABLE_1 
WHERE TABLE_1.INIT_DATE = (CASE WHEN ISDATE(@queryWord) = 1 
                                THEN CONVERT(Date, @queryWord)
                           ELSE NULL  END)

副作用,CASE和查询嵌套是我能想到的唯一两种支持的方法,可以强制在SQL中强制执行依赖条件的评估顺序。

答案 1 :(得分:2)

我猜你可以在2次传球中完成:

declare @queryWord as nvarchar(20) = 'asdas'


    select
    *
    from
    (
    SELECT  * FROM TABLE_1 
    WHERE (ISDATE(@queryWord) = 1) ) t1
    where t1.INIT_DATE = CONVERT(Date, @queryWord)

因此,您的内部查询运行第一个测试,外部查询运行第二个。在单个查询中,我认为没有任何方法可以强制任何评估条件的顺序。

答案 2 :(得分:1)

为什么不在WHERE条件下执行CASE?

DECLARE @tester TABLE (
    theDate DATE,
    theValue INT
    )

INSERT INTO @tester VALUES ('2013-10-17', 35)
INSERT INTO @tester VALUES ('2013-10-16', 50)
INSERT INTO @tester VALUES ('2013-10-15', 2)

declare @queryWord as nvarchar(20) = 'asdas'
SELECT  *
FROM @tester
WHERE theDate =
    CASE
        WHEN ISDATE(@queryWord) = 1 THEN CONVERT(Date, @queryWord)
        ELSE theDate
    END

SET @queryWord = '2013-10-17'
SELECT  *
FROM @tester
WHERE theDate =
    CASE
        WHEN ISDATE(@queryWord) = 1 THEN CONVERT(Date, @queryWord)
        ELSE theDate
    END

答案 3 :(得分:1)

在SQL语句中没有定义的评估顺序 - 除了大小写表达式之外,甚至那里的顺序没有定义为保证的结果。理论上,where子句中的条件可以并行或交替顺序完成。

案例表达式的不同之处不在于具有已定义的顺序,而在于具有保证的结果。 IOW,case when 1=1 then 0 When longrunningfunction() = 1 then 2 end保证返回零,但没有承诺不运行longrunning函数。

答案 4 :(得分:1)

可以"模拟"使用CASE语句。但是你必须使第一个条件给出TRUE值,以避免检查第二个条件:

declare @queryWord as nvarchar(20) = 'asdas'

SELECT  * 
FROM TABLE_1
WHERE (CASE 
       WHEN ISDATE(@queryWord) = 0 THEN 0 
       WHEN TABLE_1.INIT_DATE = CONVERT(Date, @queryWord) THEN 1
       ELSE 0 END) = 1