0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

TSQLでテーブルの依存関係ツリーを出力する

Posted at

外部キーが設定されたテーブルがあってdelete の順番が分からないとかデータ投入順番があるとか、そういう場合を考えて依存関係ツリーを出力するクエリーを作った

WITH 
table_dependencies as (
    select 
        dpendent_table.TABLE_SCHEMA as dpendent_table_schema,
        dpendent_table.TABLE_NAME as dpendent_table_name,
        principal_table.TABLE_SCHEMA as principal_table_schema,
        principal_table.TABLE_NAME as principal_table_name
    from 
        INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS

        inner join INFORMATION_SCHEMA.CONSTRAINT_TABLE_USAGE as dpendent_table
            on REFERENTIAL_CONSTRAINTS.CONSTRAINT_SCHEMA = dpendent_table.CONSTRAINT_SCHEMA
            and REFERENTIAL_CONSTRAINTS.CONSTRAINT_NAME = dpendent_table.CONSTRAINT_NAME

        inner join INFORMATION_SCHEMA.CONSTRAINT_TABLE_USAGE as principal_table
            on REFERENTIAL_CONSTRAINTS.UNIQUE_CONSTRAINT_SCHEMA = principal_table.CONSTRAINT_SCHEMA
            and REFERENTIAL_CONSTRAINTS.UNIQUE_CONSTRAINT_NAME = principal_table.CONSTRAINT_NAME

      where
        principal_table.TABLE_SCHEMA <> dpendent_table.TABLE_SCHEMA
        OR principal_table.TABLE_NAME <> dpendent_table.TABLE_NAME
),
dependency_path  AS (
    select 
        TABLES.TABLE_SCHEMA as dpendent_table_schema,
        TABLES.TABLE_NAME as dpendent_table_name,
        cast(null as nvarchar(128)) as principal_table_schema,
        cast(null as nvarchar(128))  as principal_table_name,
        TABLES.TABLE_SCHEMA as root_table_schema,
        TABLES.TABLE_NAME as root_table_name,
        cast('/' + TABLES.TABLE_SCHEMA + '.' + TABLES.TABLE_NAME + '/' as nvarchar(512)) as dependency,
        1 as depth
    from 
        INFORMATION_SCHEMA.TABLES
    where
        TABLE_TYPE = 'BASE TABLE'

  UNION ALL

    select 
        table_dependencies.dpendent_table_SCHEMA as dpendent_table_schema,
        table_dependencies.dpendent_table_NAME as dpendent_table_name,
        table_dependencies.principal_table_schema as principal_table_schema,
        table_dependencies.principal_table_name as principal_table_name,
        dependency_path.root_table_schema as root_table_schema,
        dependency_path.root_table_name as root_table_name,
        cast(dependency_path.dependency + table_dependencies.dpendent_table_schema + '.' + table_dependencies.dpendent_table_name + '/' as nvarchar(512)) as dependency,
        depth + 1 as depth
    from
        table_dependencies

        INNER JOIN dependency_path
            ON table_dependencies.principal_table_name = dependency_path.dpendent_table_name
),
dependency_depth as(
    select
        dpendent_table_schema,
        dpendent_table_name,
        max(depth) as max_depth
    from
        dependency_path
    group by 
        dpendent_table_schema,
        dpendent_table_name
)

SELECT distinct
  dependency_path.root_table_schema,
  dependency_path.root_table_name,
  dependency_path.principal_table_schema,
  dependency_path.principal_table_name,
  dependency_path.dpendent_table_schema,
  dependency_path.dpendent_table_name,
  SUBSTRING(dependency_path.dependency, 2, LEN(dependency_path.dependency)-2) AS dependency,
  dependency_depth.max_depth
FROM
  dependency_path
  inner join dependency_depth
    on dependency_path.dpendent_table_schema = dependency_depth.dpendent_table_schema
    and dependency_path.dpendent_table_name = dependency_depth.dpendent_table_name
WHERE
    not exists(
        select * from dependency_path as duplicates
        where
            duplicates.DEPENDENCY <> dependency_path.DEPENDENCY
            and (duplicates.DEPENDENCY like '%' + dependency_path.DEPENDENCY or duplicates.DEPENDENCY like dependency_path.DEPENDENCY + '%' )
    )

order by
  dependency_depth.max_depth,
  dependency,
  dependency_path.root_table_schema,
  dependency_path.root_table_name,
  dependency_path.principal_table_schema,
  dependency_path.principal_table_name,
  dependency_path.dpendent_table_schema,
  dependency_path.dpendent_table_name

ここでは A-B-C. D-E の依存関係があるときに A-B-C, D-E を出力する。
A-B と B-C は対象外。

dependency_depth を order by max_depth asc とするとデータ投入時の順番、 order by max_depth desc とすると delete 時の順番が出力できる。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?