最近、アプリケーションを移行しました。その過程で、SQL Server2005からSQLServer 2008R2に移行しました。
それ以来、CTEを使用した一部のSQLクエリが機能しなくなったことに気づきました。
クエリを単純化しようとしましたが、役に立ちませんでした。この次の単純なクエリ(階層の最上位の親を取得する)でさえ、以下のエラーメッセージで終わります:
コード:
DECLARE @Companies TABLE (
AccountId UNIQUEIDENTIFIER
,NAME VARCHAR(100)
,ParentAccountId UNIQUEIDENTIFIER
)
INSERT INTO @Companies
SELECT
AccountId
,NAME
,ParentAccountId
FROM AccountBase;
WITH CTE
AS (
SELECT *
,0 [Level]
FROM @Companies
UNION ALL
SELECT
CTE.accountid
,CTE.NAME
,cmp.ParentAccountId
,LEVEL + 1
FROM CTE
INNER JOIN @Companies AS cmp ON CTE.ParentAccountId = cmp.AccountId
WHERE
cmp.ParentAccountId IS NOT NULL
)
SELECT
c.AccountId
,c.NAME
,c.ParentAccountId as TopParentAccountId
FROM (
SELECT *
,MAX([Level]) OVER (PARTITION BY NAME) [MaxLevel]
FROM CTE
) c
WHERE
MaxLevel = LEVEL
エラーメッセージ(メッセージ530):
ステートメントは終了しました。ステートメントが完了する前に、最大再帰100が使い果たされました。
考えられる理由は何ですか?
前もって感謝します。
ステートメントは終了しました。ステートメントが完了する前に、最大再帰100が使い果たされました。
このエラーの明らかな理由は、クエリが100レベルを超える再帰を実行する必要があることです。したがって、OPTION (MAXRECURSION 0)
を使用して、デフォルトの100をより高い値(たとえば1000)または無制限に増やすことができます。
もう1つの可能性は、「不良データ」(つまり、id - parent_id
隣接リスト関係のサイクル)があり、無限ループに陥る適切に記述されていない再帰CTEがあることです。
特定のクエリの場合、id(親ID、たとえば(AccountId, ParentAccountId)
と値(1,2), (2,3), (3,1)
)のサイクルにより、無限の再帰ループが発生します。
テーブル内のデータでid - parent_id
関係のサイクルを確認し、クエリを修正して、無限再帰が発生しないようにすることをお勧めします。