3

データベースからテーブルを削除する際のリスクを特定しようとしています。

データベースは大規模で、数百のテーブルが含まれています。

テーブルに関連付けられた外部キーを返すクエリがあります。したがって、削除したいテーブル名をフィードすることができ、どのテーブルがその列に依存しているかがわかります。したがって、返されたテーブルも削除する必要があります。

私の問題は、これらのテーブルを削除する必要があるため、最初の結果に依存する他のテーブルを見たいということです。

そのため、一意の結果がなくなるまで、最後の実行の結果で自分自身を呼び出すクエリをループする必要があると思います。

これは可能ですか?これを行う簡単な方法はありますか?

編集:クエリは次のとおりです。

SELECT
      PK.TABLE_NAME AS PrimaryTable,
      FK.TABLE_NAME AS ForeignTable,
      PT.COLUMN_NAME AS PrimaryColumn,
      CU.COLUMN_NAME AS ForeignColumn,
      C.CONSTRAINT_NAME AS ConstraintName
FROM
INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS C
INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS FK ON C.CONSTRAINT_NAME = FK.CONSTRAINT_NAME
INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS PK ON C.UNIQUE_CONSTRAINT_NAME = PK.CONSTRAINT_NAME
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE CU ON C.CONSTRAINT_NAME = CU.CONSTRAINT_NAME
INNER JOIN (
                  SELECT i1.TABLE_NAME, i2.COLUMN_NAME
                  FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS i1
                  INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE i2 ON i1.CONSTRAINT_NAME = i2.CONSTRAINT_NAME
                  WHERE i1.CONSTRAINT_TYPE = 'PRIMARY KEY'
                  ) PT ON PT.TABLE_NAME = PK.TABLE_NAME
WHERE PK.TABLE_NAME IN
('Table1','Table2')
ORDER BY
1,2,3,4
4

3 に答える 3

2

CTEをそのまま使用してみることができます。最後の select ステートメントに実際の where 句を記述する方が簡単だと思いますが、パフォーマンスが問題になる場合は、relationsCTE (UNION ALL の上)に where 句を記述することをお勧めします。

CTE Select ステートメント

;WITH q AS (
  SELECT
        PK.TABLE_NAME AS PrimaryTable,
        FK.TABLE_NAME AS ForeignTable,
        PT.COLUMN_NAME AS PrimaryColumn,
        CU.COLUMN_NAME AS ForeignColumn,
        C.CONSTRAINT_NAME AS ConstraintName
  FROM
  INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS C
  INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS FK ON C.CONSTRAINT_NAME = FK.CONSTRAINT_NAME
  INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS PK ON C.UNIQUE_CONSTRAINT_NAME = PK.CONSTRAINT_NAME
  INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE CU ON C.CONSTRAINT_NAME = CU.CONSTRAINT_NAME
  INNER JOIN (
                    SELECT i1.TABLE_NAME, i2.COLUMN_NAME
                    FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS i1
                    INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE i2 ON i1.CONSTRAINT_NAME = i2.CONSTRAINT_NAME
                    WHERE i1.CONSTRAINT_TYPE = 'PRIMARY KEY'
                    ) PT ON PT.TABLE_NAME = PK.TABLE_NAME
)
, Relations AS (
  SELECT  PrimaryTable AS Root
          , *
  FROM    q
  UNION ALL
  SELECT  r.Root
          , q.PrimaryTable
          , q.ForeignTable
          , q.PrimaryColumn
          , q.ForeignColumn
          , q.ConstraintName
  FROM    q
          INNER JOIN Relations r ON r.ForeignTable = q.PrimaryTable
)
SELECT  *
FROM    Relations
WHERE   Root IN ('Table1','Table2')
ORDER BY
1,2,3,4
于 2013-02-04T14:09:01.717 に答える
0

テーブル名のフィールドと処理済みフラグを含むグローバル一時テーブルを作成し、初期テーブル名を追加できると思います。削除するテーブルの初期シードを使用してコードを呼び出します。結果を一時テーブルに挿入します。次に、一時テーブルの値を反復処理して結果を一時テーブルに追加し、重複を挿入しないようにして、完了したらそれぞれを処理済みとしてマークします。テーブル内のすべてのレコードが処理されるまで続行します。

于 2013-02-04T12:32:06.363 に答える