从这个问题出发,是关于使用的COALESCE简化复杂逻辑树的简洁答案。我考虑了短路。 / p6 C+ Q. A j/ u/ T- t例如,在大多数语言函数中,对参数进行综合评估,然后传递给函数。C中:8 w, e1 [# N$ x( t2 `! Z5 m. [
int f(float x,float y) return x;}f(a,a / b) ; // This will result in an error if b == 0这似乎不是COALESCESQL Server中功能的限制:2 L5 G H1 Z3 o d Y
AS TestCalcFROM FractionsDROP TABLE Fractions 0 ) AS TestCalcFROM FractionsDROP TABLE Fractions假如它正在评估分母= 0的第二种情况,那么我期待看到以下类似的错误: : E5 \0 H9 J$ [/ I! R! iMsg 8134,Level 16,State 1,Line 1Divide by zero error encountered.我发现了一些提到 ; E9 j( b: T+ i2 q3 k- v相关甲骨文。并使用。SQL! q" A9 T# A' u2 q% Q# t C0 a
Server进行了一些测试。包含用户定义函数时,短路可能会中断。 ! z$ s1 P9 }# B8 ^2 m n" e那么,这种行为应该由吗?ANSI保证标准?0 X' f+ R b( E8 v( \& N+ i
# @6 V% Y0 N. w* Z1 Y. [" Q 解决方案: - L: r1 C# _$ P, r& u 我只是看了链接的文章,可以确认短路COALESCE和ISNULL都可能失败。 # y! @; q6 S/ A' Y0 l如果涉及到任何子查询,它似乎会失败,但是它对于标量函数和硬编码值可以正常工作。0 Q4 W- J: t6 g! R
例如, ) u3 U1 S' l1 k* A8 JDECLARE @test INTSET @test = 1PRINT 'test2'SET @test = COALESCE(@test,(SELECT COUNT(*) FROM sysobjects))SELECT 'test2',@test-- OUCH,a scan through sysobjectsCOALESCE是根据ANSI实施标准CASE句子的简写形式。ISNULL不是ANSI标准的一部分.9节似乎没有明确要求短路,但它确实暗示when应返回句子中的第一个true子句。 1 [4 P% a0 L7 Q9 d: L! X这是一些适合基于标量函数的证明(我在SQL Server: u: O# w" C) L+ ]0 Z8 P4 r& a
它在2005上运行): / k/ Y1 n' A- tCREATE FUNCTION dbo.evil()RETURNS intASBEGIN -- 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 / 0ENDgoselect dbo.evil()-- takes foreverselect ISNULL(1, dbo.evil())-- very fastselect COALESCE(1, dbo.evil())-- very fast这证明CASE执行子查询的基础实现。7 Q: T; O3 |4 K; \. b
DECLARE @test INTSET @test = 1select 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.