从这个问题出发,是关于使用的COALESCE简化复杂逻辑树的简洁答案。我考虑了短路。: d2 a9 j6 L- q0 Q) M/ s- _
例如,在大多数语言函数中,对参数进行综合评估,然后传递给函数。C中:3 o W# x( D: E ~% X
int f(float x,float y) return x;}f(a,a / b) ; // This will result in an error if b == 0这似乎不是COALESCESQL Server中功能的限制: 2 I5 |+ W. U9 ?1 h& o# DAS TestCalcFROM FractionsDROP TABLE Fractions 0 ) AS TestCalcFROM FractionsDROP TABLE Fractions假如它正在评估分母= 0的第二种情况,那么我期待看到以下类似的错误: . u6 T" z1 R c6 L* _- k/ ]Msg 8134,Level 16,State 1,Line 1Divide by zero error encountered.我发现了一些提到1 R9 g( [- M6 _( Z
相关甲骨文。并使用。SQL 0 c1 O6 e/ F6 C0 Z( E6 _Server进行了一些测试。包含用户定义函数时,短路可能会中断。 $ Q+ B' C# x: x! f8 ~" k那么,这种行为应该由吗?ANSI保证标准?1 }! R4 G! n3 t7 D# d# I& u
* w5 Y8 I2 `8 g' a; y, B" {3 f2 O 解决方案: . c* s2 `( q6 E V3 G
我只是看了链接的文章,可以确认短路COALESCE和ISNULL都可能失败。# j) q$ D2 D! W& U3 o5 n8 F
如果涉及到任何子查询,它似乎会失败,但是它对于标量函数和硬编码值可以正常工作。9 z) t* k) O3 ?4 `0 L$ h5 F
例如, / i$ j- S( T1 s- e& MDECLARE @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子句。 6 ?8 I3 o7 p& l( T7 w0 s这是一些适合基于标量函数的证明(我在SQL Server9 f+ e, i$ O1 Y
它在2005上运行): ' l# y8 }/ |' u/ p5 GCREATE 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 J0 }+ x7 r3 [, D* }% ]& uDECLARE @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.