3

次の再帰 CTE クエリを使用して、テーブルの参照テーブルを下から上に検索しようとしています

With CTE_ALL AS
(
    SELECT
       1 as TopLevel, c.CONSTRAINT_NAME, cu.TABLE_NAME AS ReferencingTable,
           cu.COLUMN_NAME AS ReferencingColumn,ku.TABLE_NAME AS ReferencedTable,
           ku.COLUMN_NAME AS ReferencedColumn
      FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS c
     INNER JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE cu
           ON cu.CONSTRAINT_NAME = c.CONSTRAINT_NAME
     INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE ku
           ON ku.CONSTRAINT_NAME = c.UNIQUE_CONSTRAINT_NAME
     where cu.TABLE_NAME = 'my table name'
Union All
    SELECT
           2 as BelowLevels, c.CONSTRAINT_NAME, cu.TABLE_NAME AS ReferencingTable,
           cu.COLUMN_NAME AS ReferencingColumn,ku.TABLE_NAME AS ReferencedTable,
           ku.COLUMN_NAME AS ReferencedColumn
      FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS c
     INNER JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE cu
           ON cu.CONSTRAINT_NAME = c.CONSTRAINT_NAME
     INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE ku
           ON ku.CONSTRAINT_NAME = c.UNIQUE_CONSTRAINT_NAME
     INNER JOIN CTE_ALL CTE on CTE.ReferencedColumn = ku.COLUMN_NAME
           and CTE.ReferencedTable = ku.TABLE_NAME
)
select *
  from CTE_ALL
 where CTE_ALL.ReferencingTable = 'my table name'

次のメッセージを表示してエラーになります

Msg 530, Level 16, State 1, Line 1
The statement terminated. The maximum recursion 100 has been exhausted before
statement completion.

これは明らかに、私のクエリがすべての SQL リソースを使い果たすように意図的に計画されていることを意味します。Microsoft のデューデリジェンスにより、これが防止されます。単一のクエリを使用し、一時テーブルを使用せずに while ループなしでこれを実行できるかどうか疑問に思っています。

ルート テーブル名とルート列 ID を知っています。また、リーフ ノード テーブル名も知っていますが、リーフ ノード列名が何であるかはわかりません。

実行時にクエリを設計して実行しているため、これを見つける必要があります。このクエリでは、実行時に構築される ON 句との間に内部結合が必要です。私がしたいことが理にかなっているのかどうかわかりません。

4

1 に答える 1

2

それで、何日も試行錯誤した後、私は自分自身を助ける方法を見つけました。また、再帰的なCTEをよりよく知った後です。

役に立つかもしれないすべての人のために

これは私がファイナライズできるクエリです

DECLARE @REFERENCED_COLUMN VARCHAR(50) = 'MyColumn'
DECLARE @REFERENCING_TABLE VARCHAR(50) = 'MyTable'

    ;WITH
        CTE_Relationship (ReferencingTable, ReferencingColumn, ReferencedTable, ReferencedColumn) AS
        (
            SELECT
                CU.TABLE_NAME AS ReferencingTable, CU.COLUMN_NAME AS ReferencingColumn,
                KU.TABLE_NAME AS ReferencedTable, KU.COLUMN_NAME AS ReferencedColumn
            FROM
                INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS C
                INNER JOIN INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE CU ON CU.CONSTRAINT_NAME = C.CONSTRAINT_NAME
                INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE KU ON KU.CONSTRAINT_NAME = C.UNIQUE_CONSTRAINT_NAME
        ),
        CTE_Recursive_Relationship (ReferencingTable, ReferencingColumn, ReferencedTable, ReferencedColumn, Pass) AS
        (
            SELECT
                R.ReferencingTable, R.ReferencingColumn, R.ReferencedTable, R.ReferencedColumn, 1 AS Pass
            FROM
                CTE_Relationship R
            WHERE
                R.ReferencingTable = @REFERENCING_TABLE

        UNION ALL

            SELECT
                R.ReferencingTable, R.ReferencingColumn, R.ReferencedTable, R.ReferencedColumn, RR.Pass + 1
            FROM
                CTE_Relationship R
                INNER JOIN CTE_Recursive_Relationship RR ON R.ReferencingTable = RR.ReferencedTable
                    AND R.ReferencedColumn = @REFERENCED_COLUMN
        )
        SELECT
            DISTINCT RR.*
        FROM
            CTE_Recursive_Relationship RR
        ORDER BY RR.Pass
于 2012-11-19T21:28:37.623 に答える