171

How can I find all of the foreign key dependencies on a particular column?

What are the different alternatives (graphically in SSMS, queries/views in SQL Server, 3rd party database tools, code in .NET)?

Even Mien
  • 44,393
  • 43
  • 115
  • 119

13 Answers13

308

The following query will help to get you started. It lists all Foreign Key Relationships within the current database.

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

You can also view relationships graphically within SQL Server Management studio within Database Diagrams.

Jeremy Cook
  • 20,840
  • 9
  • 71
  • 77
John Sansom
  • 41,005
  • 9
  • 72
  • 84
  • 11
    Thanks! I just needed to add << WHERE FK.TABLE_NAME = 'MyTable' AND CU.COLUMN_NAME = 'MyColumn' >> to get the specific column. – Even Mien Jun 10 '09 at 18:16
  • 1
    +1! And if needed to get the specific column but for all tables, "WHERE CU.COLUMN_NAME = 'MyColumn'" would do. – liang Mar 06 '13 at 03:03
  • 1
    Similar to Even - I used WHERE PK.TABLE_NAME = 'MyTable' to find the table that was depended upon. – Lanceomagnifico Mar 13 '13 at 16:55
  • 7
    @samkitshah: Nobody said it would. The question is tagged sql-server, which by definition is Microsoft technology. Postgres has nothing to do with it. – Victor Zakharov Jan 09 '15 at 20:27
  • @samkitshah: Ask another question then. – Victor Zakharov Jan 12 '15 at 12:21
  • 3
    -1: This query misses foreign keys that are backed by a unique constraint or unique index, rather than by a primary key, in the referenced table. Per [MSDN](https://msdn.microsoft.com/en-us/library/ms189049.aspx): “A foreign key constraint does not have to be linked only to a primary key constraint in another table; it can also be defined to reference the columns of a UNIQUE constraint in another table.” The answer can be made to work with unique constraints by removing the last join, and with unique indexes by removing the last two joins, but that restricts the info returned. – Douglas May 30 '15 at 14:10
  • Sample foreign key that demonstrates the issue: `CREATE TABLE foo (a INT); CREATE UNIQUE INDEX UQ_foo_a ON foo (a); CREATE TABLE bar (b INT CONSTRAINT FK_bar_foo REFERENCES foo (a));`. The foreign key is correctly reported by [Mimmo's answer below](http://stackoverflow.com/a/1029305/1149773). – Douglas May 30 '15 at 14:12
  • nice, single shot query for all major Constraints in MS-Sql – Rigin Dec 01 '16 at 14:26
  • This is one of the most handy answers I've ever come across. – JacobIRR Oct 20 '17 at 18:03
104

try: sp_help [table_name]

you will get all information about table, including all foreign keys

Andrija
  • 14,037
  • 18
  • 60
  • 87
  • 2
    nice one, very useful. More memorable than the marked answer! can't believe you cant just see them in ssms! – JonnyRaa Nov 17 '14 at 17:35
  • 4
    Very nice, thanks. But for looking for FK's, I prefer the output from Michael's answer below : `sp_fkeys [table]` – AjV Jsy May 08 '15 at 11:55
  • .... or if you get no results from that (but sp_help DOES show foreign keys), the fuller version may help : `sp_fkeys @fktable_name='TableName'` – AjV Jsy May 11 '15 at 13:12
  • superb! brief and concise! – zeroflaw Feb 21 '18 at 02:21
44

Because your question is geared towards a single table, you can use this:

EXEC sp_fkeys 'TableName'

I found it on SO here:

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

I found the information I needed pretty quickly. It lists the foreign key's table, column and name.

EDIT

Here's a link to the documentation that details the different parameters that can be used: https://learn.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-fkeys-transact-sql

Community
  • 1
  • 1
Michael
  • 2,016
  • 5
  • 35
  • 51
39

If you plan on deleting or renaming a table or column finding only foreign key dependencies might not be enough.

Referencing tables not connected with foreign key - You’ll also need to search for referencing tables that might not be connected with foreign key (I’ve seen many databases with bad design that didn’t have foreign keys defined but that did have related data). Solution might be to search for column name in all tables and look for similar columns.

Other database objects – this is probably a bit off topic but if you were looking for all references than it’s also important to check for dependent objects.

GUI Tools – Try SSMS “Find related objects” option or tools such as ApexSQL Search (free tool, integrates into SSMS) to identify all dependent objects including tables connected with foreign key.

Timothy Walden
  • 676
  • 6
  • 3
32

I think this script is less expensive:

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
RobSiklos
  • 8,348
  • 5
  • 47
  • 77
6

One that I really like to use is called SQL Dependency Tracker by Red Gate Software. You can put in any database object(s) such as tables, stored procedures, etc. and it will then automatically draw the relationship lines between all the other objects that rely on your selected item(s).

Gives a very good graphical representation of the dependencies in your schema.

TheTXI
  • 37,429
  • 10
  • 86
  • 110
  • 2
    It's also a great tool for showing non-technical people that they need to spend some money on refactoring their database design before it all falls down. The graphs it generates are quite compelling. – Rob Allen May 29 '09 at 12:35
  • 1
    Rob: I like loading an entire database schema in there and then changing between the different layouts just so I can watch all the things fly around. – TheTXI May 29 '09 at 12:36
5

Thanks so much to John Sansom, his query is terrific !

In addition : you should add " AND PT.ORDINAL_POSITION = CU.ORDINAL_POSITION" at the end of your query.

If you have multiple fields in primary key, this statement will match the corresponding fields to each other (I had the case, your query did create all combinations, so for 2 fields in primary key, I had 4 results for the corresponding foreign key).

(Sorry I can't comment John's answer as I don't have enough reputation points).

Sierramike
  • 371
  • 4
  • 16
3

This query will return details about foreign keys in a table, it supports multiple column keys.

    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'
Kumait
  • 702
  • 8
  • 15
3

After long search I found a working solution. My database does not use the sys.foreign_key_columns and the information_schema.key_column_usage only contain primary keys.

I use SQL Server 2015

SOLUTION 1 (rarely used)

If other solutions does not work, this will work fine:

        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

SOLUTION 2 (commonly used)

In most of the cases this will work just fine:

        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
profimedica
  • 2,716
  • 31
  • 41
2

You can Use INFORMATION_SCHEMA.KEY_COLUMN_USAGE and sys.foreign_key_columns in order to get the foreign key metadata for a table i.e. Constraint name, Reference table and Reference column etc.

Below is the query:

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

Just a note for @"John Sansom" answer,

If the foreign key dependencies are sought, I think that the PT Where clause should be:

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

and its the ON condition:

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

As commonly is used the primary key of the foreign table, I think this issue has not been noticed before.

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

It will give you:

The FK itself Schema that the FK belongs to

  • The "referencing table" or the table that has the FK
  • The "referencing column" or the column inside referencing table that points to the FK
  • The "referenced table" or the table that has the key column that your FK is pointing to
  • The "referenced column" or the column that is the key that your FK is pointing to
Divya Agrawal
  • 300
  • 1
  • 2
  • 15
-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)
bobs
  • 21,844
  • 12
  • 67
  • 78
dave
  • 1