9

我正在尝试在 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) = 1is false,我期望 SQL检查第二个条件,但显然,它确实如此。

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

4

5 回答 5

13

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 中的依赖条件进行评估顺序。

于 2013-10-17T14:25:00.993 回答
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)

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

于 2013-10-17T14:23:54.067 回答
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
于 2013-10-17T14:26:59.833 回答
1

There is no defined evaluation order in a SQL statement -- except in the case of case expressions, and even there the order isn't so much defined as the result guaranteed. The conditions in your where clause could theoretically be done in parallel or alternating order.

Case expressions differ not by having a defined order, but by having a guaranteed result. IOW, case when 1=1 then 0 When longrunningfunction() = 1 then 2 end is guaranteed to return zero, but there is no promise not to run the longrunningfunction.

于 2013-10-17T15:22:34.280 回答
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
于 2013-10-17T17:50:37.707 回答