web-dev-qa-db-ja.com

データベースの移行後にCTEを使用したSQLクエリが機能しない

最近、アプリケーションを移行しました。その過程で、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が使い果たされました。

考えられる理由は何ですか?

前もって感謝します。

2
salcoin

ステートメントは終了しました。ステートメントが完了する前に、最大再帰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関係のサイクルを確認し、クエリを修正して、無限再帰が発生しないようにすることをお勧めします。

4
ypercubeᵀᴹ