SQL Serverで外部キーの依存関係を見つける方法は?


163

特定の列のすべての外部キー依存関係を見つけるにはどうすればよいですか?

別の選択肢は何ですか(SSMSでのグラフィック、SQL Serverでのクエリ/ビュー、サードパーティのデータベースツール、.NETでのコード)。

回答:


290

次のクエリは、開始するのに役立ちます。現在のデータベース内のすべての外部キー関係をリストします。

SELECT
    FK_Table = FK.TABLE_NAME,
    FK_Column = CU.COLUMN_NAME,
    PK_Table = PK.TABLE_NAME,
    PK_Column = PT.COLUMN_NAME,
    Constraint_Name = C.CONSTRAINT_NAME
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

データベースダイアグラム内のSQL Server Management Studio内でグラフィカルに関係を表示することもできます。


8
ありがとう!特定の列を取得するには、<< WHERE FK.TABLE_NAME = 'MyTable' AND CU.COLUMN_NAME = 'MyColumn' >>を追加するだけです。
Mien

1
+1!また、特定の列を取得する必要があるが、すべてのテーブルの場合、「WHERE CU.COLUMN_NAME = 'MyColumn'」で実行されます。
リャン2013年

1
Evenと同様-依存しているテーブルを見つけるためにWHERE PK.TABLE_NAME = 'MyTable'を使用しました。
Lanceomagnifico 2013年

7
@samkitshah:誰もそうは言わなかった。質問にはsql-serverというタグが付いています。これは、定義上、Microsoftのテクノロジーです。Postgresはそれとは何の関係もありません。
Neolisk

2
-1:このクエリは、参照されるテーブルの主キーではなく、一意性制約または一意性インデックスに基づく外部キーを見逃します。パーMSDN:「外部キー制約のみを別のテーブルの主キー制約にリンクする必要はありません。別のテーブルのUNIQUE制約の列を参照するように定義することもできます。」答えは、最後の結合を削除することで一意の制約で動作し、最後の2つの結合を削除することで一意のインデックスで動作するようにできますが、返される情報が制限されます。
ダグラス

100

試してください: sp_help [table_name]

すべての外部キーを含む、テーブルに関するすべての情報を取得します


2
とても便利です。マークされた答えよりも記憶に残る!あなたがそれらをssmsで見るだけでは信じられない!
JonnyRaa 2014年

4
とてもいいですありがとう :しかし、FKさんを探しているために、私は以下のマイケルの答えからの出力を好む sp_fkeys [table]
AJV JSY

あなたはそれから何の結果を得るていない(ただし、sp_helpは外部キーを示していた場合)....または、より完全なバージョンが役立つ可能性がありますsp_fkeys @fktable_name='TableName'
AJV JSY

見事!簡潔で簡潔です!
zeroflaw 2018

39

テーブルまたは列の削除または名前の変更を計画している場合は、外部キーの依存関係のみを見つけるだけでは不十分な場合があります。

外部キーに接続されていない参照テーブル - 外部キーに接続されていない可能性のある参照テーブルも検索する必要があります(外部キーが定義されていないが、関連するデータが含まれている設計の悪い多くのデータベースを見てきました)。解決策は、すべてのテーブルで列名を検索し、同様の列を探すことです。

他のデータベースオブジェクト –これはおそらく少し外れたトピックですが、すべての参照を探すよりも、依存オブジェクトをチェックすることが重要です。

GUIツール– SSMSの[関連オブジェクトを検索]オプションまたはApexSQL Search(無料ツール、SSMSに統合)などのツールを試して、外部キーに接続されたテーブルを含むすべての依存オブジェクトを識別します。


39

あなたの質問は単一のテーブルに向けられているので、これを使うことができます:

EXEC sp_fkeys 'TableName'

私はSOのここでそれを見つけました:

https://stackoverflow.com/a/12956348/652519

必要な情報がすぐに見つかりました。外部キーのテーブル、列、名前がリストされます。

編集

使用できるさまざまなパラメーターの詳細を説明したドキュメントへのリンクは次のとおりです。https//docs.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-fkeys-transact-sql


29

このスクリプトの方が安価だと思います。

SELECT f.name AS ForeignKey, OBJECT_NAME(f.parent_object_id) AS TableName,
    COL_NAME(fc.parent_object_id, fc.parent_column_id) AS ColumnName,
    OBJECT_NAME (f.referenced_object_id) AS ReferenceTableName,
    COL_NAME(fc.referenced_object_id, fc.referenced_column_id) AS ReferenceColumnName
FROM sys.foreign_keys AS f
INNER JOIN sys.foreign_key_columns AS fc
ON f.OBJECT_ID = fc.constraint_object_id

6

私が本当に使いたいのは、Red Gate Softwareの SQL Dependency Tracker です。。テーブル、ストアドプロシージャなどのデータベースオブジェクトを配置すると、選択したアイテムに依存する他のすべてのオブジェクト間の関係線が自動的に描画されます。

スキーマ内の依存関係の非常に優れたグラフィック表現を提供します。


2
また、技術者以外の人々に、データベースの設計がすべて失敗する前に、データベース設計のリファクタリングにいくらかお金をかける必要があることを示すための優れたツールでもあります。それが生成するグラフは非常に説得力があります。
ロブ・アレン

1
Rob:データベーススキーマ全体をそこに読み込んでから、さまざまなレイアウトを変更して、すべてのものが飛び交うのを見ることが好きです。
TheTXI 2009年

4

John Sansomに感謝します。彼のクエリはすばらしいです。

さらに、クエリの最後に「AND PT.ORDINAL_POSITION = CU.ORDINAL_POSITION」を追加する必要があります。

主キーに複数のフィールドがある場合、このステートメントは対応するフィールドを相互に一致させます(私は、クエリがすべての組み合わせを作成したため、主キーの2つのフィールドに対して、対応する外部キーに対して4つの結果がありました)。 。

(申し訳ありませんが、十分な評判ポイントがないため、ジョンの答えにはコメントできません)。


3

このクエリは、テーブル内の外部キーに関する詳細を返します。複数の列キーをサポートしています。

    SELECT *
    FROM
    (
    SELECT 
    T1.constraint_name ConstraintName,
    T2.COLUMN_NAME ColumnName,
    T3.TABLE_NAME RefTableName, 
    T3.COLUMN_NAME RefColumnName,
    T1.MATCH_OPTION MatchOption, 
    T1.UPDATE_RULE UpdateRule, 
    T1.DELETE_RULE DeleteRule
    FROM 
    INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS T1
    INNER JOIN
    INFORMATION_SCHEMA.KEY_COLUMN_USAGE T2 
    ON T1.CONSTRAINT_NAME = T2.CONSTRAINT_NAME
    INNER JOIN
    INFORMATION_SCHEMA.KEY_COLUMN_USAGE T3 
    ON T1.UNIQUE_CONSTRAINT_NAME = T3.CONSTRAINT_NAME 
    AND T2.ORDINAL_POSITION = T3.ORDINAL_POSITION) A
    WHERE A.ConstraintName = 'table_name'

2

長い検索の結果、実用的な解決策が見つかりました。私のデータベースはsys.foreign_key_columnsを使用せず、information_schema.key_column_usageには主キーしか含まれていません。

SQL Server 2015を使用しています

ソリューション1(まれに使用)

他のソリューションが機能しない場合、これは正常に機能します。

        WITH CTE AS
        (
            SELECT 
                TAB.schema_id,
                TAB.name,
                COL.name AS COLNAME,
                COl.is_identity
            FROM 
                sys.tables TAB INNER JOIN sys.columns COL 
                    ON TAB.object_id = COL.object_id
        )
        SELECT 
            DB_NAME() AS [Database], 
            SCHEMA_NAME(Child.schema_id) AS 'Schema',
            Child.name AS 'ChildTable',
            Child.COLNAME AS 'ChildColumn',
            Parent.name AS 'ParentTable',
            Parent.COLNAME AS 'ParentColumn'
        FROM 
            cte Child INNER JOIN CTE Parent
                ON 
                    Child.COLNAME=Parent.COLNAME AND 
                    Child.name<>Parent.name AND 
                    Child.is_identity+1=Parent.is_identity

ソリューション2(一般的に使用される)

ほとんどの場合、これは問題なく機能します。

        SELECT
            DB_NAME() AS [Database], 
            SCHEMA_NAME(fk.schema_id) AS 'Schema',
            fk.name 'Name',
            tp.name 'ParentTable',
            cp.name 'ParentColumn',
            cp.column_id,
            tr.name 'ChildTable',
            cr.name 'ChildColumn',
            cr.column_id
        FROM
            sys.foreign_keys fk
        INNER JOIN
            sys.tables tp ON fk.parent_object_id = tp.object_id
        INNER JOIN
            sys.tables tr ON fk.referenced_object_id = tr.object_id
        INNER JOIN
            sys.foreign_key_columns fkc ON fkc.constraint_object_id = fk.object_id
        INNER JOIN
            sys.columns cp ON fkc.parent_column_id = cp.column_id AND fkc.parent_object_id = cp.object_id
        INNER JOIN
            sys.columns cr ON fkc.referenced_column_id = cr.column_id AND fkc.referenced_object_id = cr.object_id
        WHERE 
            -- CONCAT(SCHEMA_NAME(fk.schema_id), '.', tp.name, '.', cp.name) LIKE '%my_table_name%' OR
            -- CONCAT(SCHEMA_NAME(fk.schema_id), '.', tr.name, '.', cr.name) LIKE '%my_table_name%' 
        ORDER BY
            tp.name, cp.column_id

2

テーブルの外部キーメタデータ(制約名、参照テーブル、参照列など)を取得するには、INFORMATION_SCHEMA.KEY_COLUMN_USAGEおよびsys.foreign_key_columnsを使用できます。

以下はクエリです:

SELECT  CONSTRAINT_NAME, COLUMN_NAME, ParentTableName, RefTableName,RefColName FROM 
    (SELECT CONSTRAINT_NAME,COLUMN_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE TABLE_NAME = '<tableName>') constraint_details
    INNER JOIN  
    (SELECT ParentTableName, RefTableName,name ,COL_NAME(fc.referenced_object_id,fc.referenced_column_id) RefColName  FROM (SELECT object_name(parent_object_id) ParentTableName,object_name(referenced_object_id) RefTableName,name,OBJECT_ID  FROM sys.foreign_keys WHERE parent_object_id = object_id('<tableName>') ) f 
    INNER JOIN   
    sys.foreign_key_columns AS fc  ON  f.OBJECT_ID = fc.constraint_object_id ) foreign_key_detail 
    on foreign_key_detail.name = constraint_details.CONSTRAINT_NAME

1

@ "John Sansom"の回答に対するメモ

場合は、外部キーの依存性が求められている、私は句がすべきことであるが、PTだと思います。

i1.CONSTRAINT_TYPE = 'FOREIGN KEY'  -- instead of 'PRIMARY KEY'

そしてそのON条件:

ON PT.TABLE_NAME = FK.TABLE_NAME  instead of PK.TABLE_NAME

一般的に外部テーブルの主キーが使用されるので、この問題は以前には気づかなかったと思います。


0
SELECT  obj.name AS FK_NAME,
    sch.name AS [schema_name],
    tab1.name AS [table],
    col1.name AS [column],
    tab2.name AS [referenced_table],
    col2.name AS [referenced_column]
FROM sys.foreign_key_columns fkc
INNER JOIN sys.objects obj
    ON obj.object_id = fkc.constraint_object_id
INNER JOIN sys.tables tab1
    ON tab1.object_id = fkc.parent_object_id
INNER JOIN sys.schemas sch
    ON tab1.schema_id = sch.schema_id
INNER JOIN sys.columns col1
    ON col1.column_id = parent_column_id AND col1.object_id = tab1.object_id
INNER JOIN sys.tables tab2
    ON tab2.object_id = fkc.referenced_object_id
INNER JOIN sys.columns col2
    ON col2.column_id = referenced_column_id AND col2.object_id = tab2.object_id

それはあなたに与えるでしょう:

FKが属するFK自体のスキーマ

  • 「参照テーブル」またはFKを持つテーブル
  • 「参照列」またはFKを指す参照テーブル内の列
  • 「参照されたテーブル」またはFKが指しているキー列を持つテーブル
  • 「参照列」またはFKが指しているキーである列

-1

USE information_schema;

SELECT COLUMN_NAME, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME
FROM KEY_COLUMN_USAGE
WHERE (table_name = *tablename*) AND NOT (REFERENCED_TABLE_NAME IS NULL)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.