这个问题, 一个整洁的回答关于使用聚结 为了简化复杂逻辑的树木。我认为这一问题的短路。

例如,在功能在于大多数语言、论据充分的评估和随后通过了进入功能。C:

int f(float x, float y) {
    return x;
}

f(a, a / b) ; // This will result in an error if b == 0

这似乎不是一个限制 COALESCE "功能"SQL服务器:

CREATE TABLE Fractions (
    Numerator float
    ,Denominator float
)

INSERT INTO Fractions VALUES (1, 1)
INSERT INTO Fractions VALUES (1, 2)
INSERT INTO Fractions VALUES (1, 3)
INSERT INTO Fractions VALUES (1, 0)
INSERT INTO Fractions VALUES (2, 0)
INSERT INTO Fractions VALUES (3, 0)

SELECT Numerator
    ,Denominator
    ,COALESCE(
        CASE WHEN Denominator = 0 THEN 0 ELSE NULL END,
        CASE WHEN Numerator <> 0 THEN Numerator / Denominator ELSE NULL END,
        0
    ) AS TestCalc
FROM Fractions

DROP TABLE Fractions

如果这是评价第二种情况下,当母=0,我希望看到一个错误,如:

Msg 8134, Level 16, State 1, Line 1
Divide by zero error encountered.

我找到一些 提到了 相关的 Oracle。和一些测试 SQL服务器.看起来像短路可能会打破当包括用户定义的功能。

因此,这种行为应该保证通过ANSI标准?

有帮助吗?

解决方案

我刚刚看了一下链接的文章,可以确认短路可都失败COALESCE和ISNULL。

看来,如果您有任何子查询涉及到失败,但它工作正常的标量函数和硬编码值。

例如,

DECLARE @test INT
SET @test = 1
PRINT 'test2'
SET @test = COALESCE(@test, (SELECT COUNT(*) FROM sysobjects))
SELECT 'test2', @test
-- OUCH, a scan through sysobjects

COALESCE根据 ANSI标准实现。这简直就是一个CASE语句的简写。 ISNULL不是ANSI标准的一部分。 6.9节似乎并不需要短路明确,但它确实意味着在when语句中的第一个真正的条款应被退回。

下面是一些证明是基于标量函数作品(我跑了它在的SQL Server 2005 ):

CREATE FUNCTION dbo.evil
(
)
RETURNS int
AS
BEGIN
    -- Create an huge delay
    declare @c int
    select @c = count(*) from sysobjects a
    join sysobjects b on 1=1
    join sysobjects c on 1=1
    join sysobjects d on 1=1
    join sysobjects e on 1=1
    join sysobjects f on 1=1
    return @c / 0
END
go

select dbo.evil()
-- takes forever

select ISNULL(1,  dbo.evil())
-- very fast

select COALESCE(1,  dbo.evil())
-- very fast

下面是一些证明与CASE底层实现将执行子查询。

DECLARE @test INT
SET @test = 1
select
    case
        when @test is not null then @test
        when @test = 2 then (SELECT COUNT(*) FROM sysobjects)
        when 1=0 then (SELECT COUNT(*) FROM sysobjects)
        else (SELECT COUNT(*) FROM sysobjects)
    end
-- OUCH, two table scans. If 1=0, it does not result in a table scan.

其他提示

高效办法保证短路MS SQL Server中是使用CASE。 对于成功WHEN子句,没有其它的评价。

COALESCE可以具有

在这种情况下,为什么在COALESCE / CASE这么多分支构造?

SELECT Numerator
    ,Denominator
    ,CASE
        WHEN Denominator = 0 THEN 0 END,
        ELSE Numerator / Denominator
     END AS TestCalc
FROM Fractions

我也惊讶地看到这个问题的答案的作品!我不知道这种行为是保证。 (但我一直没能找到不工作的例子!)

五年 SQL ,我仍然感到惊讶。

我也说干就干,做了一个多变化:

INSERT INTO #Fractions VALUES (0, 0)

SELECT Numerator
    ,Denominator
    ,coalesce (
        CASE WHEN Denominator = 0 THEN 0 ELSE NULL END,
        CASE WHEN Numerator <> 0 THEN Numerator / Denominator ELSE NULL END)
     AS TestCalc
FROM #Fractions

我得到的结果是:

Numerator   Denominator TestCalc
1             1           1
1             2           0.5
1             3           0.3333333333333335
1             0           0
2             0           0
3             0           0
0             0           0

现在我更糊涂了!对于情况下NUM = 0和书房= 0,我怎么得到testcalc为0(尤其是因为我过去的情况后取出0!)?

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top