2012-01-16 7 views
5

は現在、我々はそれのテーブルからデータを返すストアドプロシージャは、このような何かを実行して、元のスキーマだていますので、どんなにテーブルのスキーマの変更CTEの再帰の深さを制限する方法はありますが、汎用テーブルを選択するにはどうすればよいですか?

WITH CTE AS 
(
    -- Start CTE off by selecting the id that was provided to stored procedure. 
    SELECT * 
    FROM [dbo].[TestTable] 
    WHERE [Id] = 1 
    -- Recursively add tasks that are children of records already found in previous iterations. 
    UNION ALL 
    SELECT t.* 
    FROM [dbo].[TestTable] as t 
    INNER JOIN CTE as tcte 
     ON t.[ParentId] = tcte.[Id] 
)   
SELECT * 
FROM CTE 

これは限り[があるので、いいですId]と[ParentId]列を使用しているため、このストアドプロシージャを更新する必要はありません。私は同様のことをしたいと思いますが、再帰の深度を動的に指定することもできます。私はこれを行うに見てきた唯一の方法はそうのようなレベル/深さの識別子を追加することです:

WITH CTE AS 
(
    -- Start CTE off by selecting the task that was provided to stored procedure. 
    SELECT *, 0 as [Level] 
    FROM [dbo].[TestTable] 
    WHERE [Id] = 1 
    -- Recursively add tasks that are children of parent tasks that have already been found in previous iterations. 
    UNION ALL 
    SELECT t.*, [Level] + 1 
    FROM [dbo].[TestTable] as t 
    INNER JOIN CTE as tcte 
     ON t.[ParentId] = tcte.[Id] 
    WHERE [Level] < 2 
)   
SELECT * 
FROM CTE 

これはうまく動作しますが、*を選択するので、最後に前のクエリの主要なプラスを奪うが得られます私もレベル。私はレベルを指定することができますが、一般的にテーブルからすべての列を選択することができるこの他の方法がありますか?前もって感謝します。

答えて

12

あなたがあなたのレベルのフィールドで行いたいことが制限再帰の数である場合は、MAXRECURSION query hint、このようなものを使用することができる必要があります:への答えでは

WITH Department_CTE AS 
(
    SELECT 
     DepartmentGroupKey, 
     ParentDepartmentGroupKey, 
     DepartmentGroupName 
    FROM dimDepartmentGroup 
    WHERE DepartmentGroupKey = 2 
    UNION ALL 
    SELECT 
     Child.DepartmentGroupKey, 
     Child.ParentDepartmentGroupKey, 
     Child.DepartmentGroupName 
    FROM Department_CTE AS Parent 
     JOIN DimDepartmentGroup AS Child 
      ON Parent.ParentDepartmentGroupKey = Child.DepartmentGroupKey 
) 
SELECT * FROM Department_CTE 
OPTION (MAXRECURSION 2) 

編集をコメントの質問、いいえ、MAXRECURSION設定で許される回数よりも多くの時間を繰り返すときに発生するエラーを抑制することはできません。私が正しくあなたを理解していれば、あなたはこのような何かを行うことができ:

WITH CTE AS 
(
    -- Start CTE off by selecting the task that was provided to stored procedure. 
    SELECT Id, 0 as [Level] 
    FROM [dbo].[TestTable] 
    WHERE [Id] = 1 
    -- Recursively add tasks that are children of parent tasks that have already been found in previous iterations. 
    UNION ALL 
    SELECT t.Id, [Level] + 1 
    FROM [dbo].[TestTable] as t 
    INNER JOIN CTE as tcte 
     ON t.[ParentId] = tcte.[Id] 
    WHERE [Level] < 2 
), 
CTE2 AS 
(
    SELECT TestTable.* 
    FROM CTE 
     INNER JOIN TestTable ON CTE.Id = TestTable.Id 
) 
SELECT * FROM CTE2; 

これは、あなたが、階層または主キーのフィールドを変更することを計画していないと仮定すると、上記の持っているものと同等として汎用的にする必要があります。

+0

制限値に達するとエラーが表示されるようです。 MAXRECURSIONに基づいて停止する方法はありますか? – Ocelot20

+0

上記(別の提案と共に)... – mwigdahl

関連する問題