目的
自己参照関数のテスト例を作成しようとすると、あるバージョンが失敗し、別のバージョンが成功します。
唯一の違いはSELECT
、関数本体に追加されることです。その結果、両方で異なる実行計画が作成されます。
機能する機能
CREATE FUNCTION dbo.test5(@i int)
RETURNS INT
AS
BEGIN
RETURN(
SELECT TOP 1
CASE
WHEN @i = 1 THEN 1
WHEN @i = 2 THEN 2
WHEN @i = 3 THEN dbo.test5(1) + dbo.test5(2)
END
)
END;
関数を呼び出す
SELECT dbo.test5(3);
返品
(No column name)
3
機能しない機能
CREATE FUNCTION dbo.test6(@i int)
RETURNS INT
AS
BEGIN
RETURN(
SELECT TOP 1
CASE
WHEN @i = 1 THEN 1
WHEN @i = 2 THEN 2
WHEN @i = 3 THEN (SELECT dbo.test6(1) + dbo.test6(2))
END
)END;
関数を呼び出す
SELECT dbo.test6(3);
または
SELECT dbo.test6(2);
エラーの結果
ストアドプロシージャ、関数、トリガー、またはビューのネストレベルが最大値を超えています(制限32)。
原因を推測する
失敗した関数の推定プランに追加の計算スカラーがあり、呼び出し
<ColumnReference Column="Expr1002" />
<ScalarOperator ScalarString="CASE WHEN [@i]=(1) THEN (1) ELSE CASE WHEN [@i]=(2) THEN (2) ELSE CASE WHEN [@i]=(3) THEN [Expr1000] ELSE NULL END END END">
そしてexpr1000
<ColumnReference Column="Expr1000" />
<ScalarOperator ScalarString="[dbo].[test6]((1))+[dbo].[test6]((2))">
32を超える再帰参照を説明できます。
実際の質問
追加SELECT
すると、関数自体が何度も呼び出され、無限ループが発生しますが、なぜSELECT
この結果を追加するのですか?
追加情報
Build version:
14.0.3045.24
compatibility_levels 100および140でテスト済み