11

this questionから、COALESCEを使用して複雑なロジック ツリーを単純化することに関する適切な回答です。短絡の問題を考えました。

たとえば、ほとんどの言語の関数では、引数は完全に評価されてから関数に渡されます。C:

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

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

COALESCEこれは、SQL Server の「機能」の制限ではないようです。

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 の 2 番目のケースを評価している場合、次のようなエラーが表示されると予想されます。

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

オラクルに関連するいくつかの言及 を見つけました。そしてSQL Serverでのいくつかのテスト。ユーザー定義関数を含めると、短絡が壊れる可能性があるようです。

では、この動作は ANSI 標準で保証されているのでしょうか?

4

3 に答える 3

1

その答えがうまくいくのを見て私も驚きました!この動作が保証されているかどうかはわかりません。(しかし、うまくいかない例を見つけることができませんでした!)

5 年間SQLを使用してきましたが、今でも驚いています。

私も先に進み、もう1つの変更を行いました:

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 および den=0 の場合、どのようにして testcalc を 0 にしましたか (特に最後のケースの後に 0 を削除したため!)?

于 2009-02-03T04:21:26.573 に答える