Как найти зависимости внешнего ключа в SQL Server? - PullRequest
160 голосов
/ 29 мая 2009

Как найти все зависимости внешнего ключа для определенного столбца?

Какие существуют альтернативы (графически в SSMS, запросах / представлениях в SQL Server, сторонних инструментах баз данных, коде в .NET)?

Ответы [ 13 ]

282 голосов
/ 29 мая 2009

Следующий запрос поможет вам начать. В нем перечислены все отношения внешних ключей в текущей базе данных.

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 в диаграммах базы данных.

99 голосов
/ 29 мая 2009

попробуй: sp_help [table_name]

Вы получите всю информацию о таблице, включая все внешние ключи

39 голосов
/ 27 марта 2013

Если вы планируете удалить или переименовать таблицу или столбец, найти только зависимости внешнего ключа может быть недостаточно.

Ссылки на таблицы, не связанные с внешним ключом - Вам также потребуется поискать таблицы ссылок, которые могут быть не связаны с внешним ключом (я видел много баз данных с плохим дизайном, которые не имели внешние ключи определены, но у них есть связанные данные). Решением может быть поиск имени столбца во всех таблицах и поиск похожих столбцов.

Другие объекты базы данных - это, вероятно, немного не по теме, но если вы искали все ссылки, важно также проверить наличие зависимых объектов.

Инструменты с графическим интерфейсом - попробуйте SSMS «Найти связанные объекты» или такие инструменты, как ApexSQL Search (бесплатный инструмент, интегрируется в SSMS) для идентификации всех зависимых объектов, включая таблицы, связанные с внешним ключом.

38 голосов
/ 21 ноября 2014

Поскольку ваш вопрос предназначен для одной таблицы, вы можете использовать это:

EXEC sp_fkeys 'TableName'

Я нашел это на SO здесь:

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

Я нашел нужную мне информацию довольно быстро. В нем перечислены таблица, столбец и имя внешнего ключа.

EDIT

Вот ссылка на документацию, в которой подробно описаны различные параметры, которые можно использовать: https://docs.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-fkeys-transact-sql

28 голосов
/ 23 июня 2009

Я думаю, что этот скрипт дешевле:

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 голосов
/ 29 мая 2009

Тот, который мне действительно нравится использовать, называется SQL Dependency Tracker от Red Gate Software . Вы можете добавить любой объект (ы) базы данных, такие как таблицы, хранимые процедуры и т. Д., И тогда он автоматически проведет линии отношений между всеми другими объектами, которые зависят от выбранных вами элементов.

Дает очень хорошее графическое представление зависимостей в вашей схеме.

4 голосов
/ 12 февраля 2014

Большое спасибо Джону Сэнсому, его запрос потрясающий!

Кроме того: вы должны добавить «AND PT.ORDINAL_POSITION = CU.ORDINAL_POSITION» в конце вашего запроса.

Если у вас есть несколько полей в первичном ключе, этот оператор будет сопоставлять соответствующие поля друг с другом (у меня был случай, ваш запрос создал все комбинации, поэтому для 2 полей в первичном ключе у меня было 4 результата для соответствующего внешний ключ).

(Извините, я не могу прокомментировать ответ Джона, так как у меня недостаточно очков репутации).

3 голосов
/ 11 апреля 2014

Этот запрос вернет сведения о внешних ключах в таблице, он поддерживает несколько ключей столбцов.

    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 голосов
/ 13 февраля 2019

Вы можете использовать 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
2 голосов
/ 09 мая 2017

После долгих поисков я нашел рабочее решение. Моя база данных не использует 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...