CASE
/ COALESCE
短絡しない別のケースに出くわしました。次のTVFは1
、パラメーターとして渡されるとPK違反を発生させます。
CREATE FUNCTION F (@P INT)
RETURNS @T TABLE (
C INT PRIMARY KEY)
AS
BEGIN
INSERT INTO @T
VALUES (1),
(@P)
RETURN
END
次のように呼び出された場合
DECLARE @Number INT = 1
SELECT COALESCE(@Number, (SELECT number
FROM master..spt_values
WHERE type = 'P'
AND number = @Number),
(SELECT TOP (1) C
FROM F(@Number)))
またはとして
DECLARE @Number INT = 1
SELECT CASE
WHEN @Number = 1 THEN @Number
ELSE (SELECT TOP (1) C
FROM F(@Number))
END
両方とも結果を与える
PRIMARY KEY制約 'PK__F__3BD019A800551192'の違反。オブジェクト 'dbo。@ T'に重複キーを挿入できません。重複キー値は(1)です。
ことを示しているSELECT
(あるいは少なくとも、テーブル変数人口)がまだ行われ、文の分岐が到達すべきではないにもかかわらず、エラーを発生させています。COALESCE
バージョンの計画は以下のとおりです。
このクエリの書き換えは、問題を回避するようです
SELECT COALESCE(Number, (SELECT number
FROM master..spt_values
WHERE type = 'P'
AND number = Number),
(SELECT TOP (1) C
FROM F(Number)))
FROM (VALUES(1)) V(Number)
計画を与える
CASE
常に左から右、常に短絡を評価します)。