How to find foreign key dependencies in SQL Server?
Asked Answered
K

13

172

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)?

Kalman answered 29/5, 2009 at 12:29 Comment(0)
R
309

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.

Ritch answered 29/5, 2009 at 12:34 Comment(9)
Thanks! I just needed to add << WHERE FK.TABLE_NAME = 'MyTable' AND CU.COLUMN_NAME = 'MyColumn' >> to get the specific column.Kalman
+1! And if needed to get the specific column but for all tables, "WHERE CU.COLUMN_NAME = 'MyColumn'" would do.Cavorelievo
Similar to Even - I used WHERE PK.TABLE_NAME = 'MyTable' to find the table that was depended upon.Leanoraleant
@samkitshah: Nobody said it would. The question is tagged sql-server, which by definition is Microsoft technology. Postgres has nothing to do with it.Amputee
@samkitshah: Ask another question then.Amputee
-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: “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.Hypersonic
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.Hypersonic
nice, single shot query for all major Constraints in MS-SqlMagenmagena
This is one of the most handy answers I've ever come across.Boiney
D
104

try: sp_help [table_name]

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

Demetricedemetris answered 29/5, 2009 at 12:37 Comment(4)
nice one, very useful. More memorable than the marked answer! can't believe you cant just see them in ssms!Validity
Very nice, thanks. But for looking for FK's, I prefer the output from Michael's answer below : sp_fkeys [table]Brockway
.... 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'Brockway
superb! brief and concise!Teledu
P
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://mcmap.net/q/53249/-how-can-i-list-all-foreign-keys-referencing-a-given-table-in-sql-server

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

Phalanx answered 20/11, 2014 at 21:46 Comment(0)
S
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.

Sharlenesharline answered 27/3, 2013 at 12:7 Comment(0)
B
33

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
Bubbler answered 22/6, 2009 at 20:46 Comment(0)
C
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.

Clarence answered 29/5, 2009 at 12:33 Comment(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.Imperious
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.Clarence
A
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).

Alger answered 12/2, 2014 at 10:33 Comment(0)
D
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'
Danforth answered 11/4, 2014 at 1:55 Comment(0)
M
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
Mcwherter answered 9/5, 2017 at 16:32 Comment(1)
This (2) is the correct answer. All the others give wrong results when 2 tables are joined on more than one columnNeron
J
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
Jeffereyjefferies answered 13/2, 2019 at 8:51 Comment(0)
L
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.

Like answered 6/4, 2015 at 20:57 Comment(0)
I
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
Initial answered 28/3, 2019 at 13:23 Comment(0)
A
-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)
Amen answered 21/2, 2013 at 23:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.