Как найти зависимости внешнего ключа в SQL Server?
Как я могу найти все зависимости внешнего ключа для определенного столбца?
каковы различные альтернативы (графически в SSMS, запросах / представлениях в SQL Server, сторонних инструментах баз данных, коде в .NET)?
11 ответов
следующий запрос поможет вам начать. В нем перечислены все связи внешнего ключа в текущей базе данных.
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 в диаграммах базы данных.
Если вы планируете удалить или переименовать таблицу или столбец, может быть недостаточно найти только зависимости внешнего ключа.
ссылки на таблицы, не связанные с внешним ключом - вам также нужно будет искать ссылки на таблицы, которые могут быть не связаны с внешним ключом (я видел много баз данных с плохим дизайном, которые не имели внешних ключей, но которые имели связанные данные). Решением может быть поиск имени столбца во всех таблицах и поиск похожих столбцы.
другие объекты базы данных - это, вероятно, немного не по теме, но если вы искали все ссылки, то также важно проверить наличие зависимых объектов.
GUI Tools-попробуйте SSMS" найти связанные объекты " или такие инструменты, как Поиск ApexSQL (бесплатный инструмент, интегрируется в SSMS) для идентификации всех зависимых объектов, включая таблицы, связанные с внешним ключом.
поскольку ваш вопрос ориентирован на одну таблицу, вы можете использовать это:
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
Я думаю, что этот скрипт дешевле:
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
тот, который мне очень нравится использовать, называется SQL Dependency Tracker by Red Gate Software. Вы можете поместить в любой объект базы данных(ы), такие как таблицы, хранимые процедуры и т. д. и он будет автоматически рисовать линии отношений между всеми другими объектами, которые полагаются на выбранный элемент(ы).
дает очень хорошее графическое представление зависимостей в схеме.
большое спасибо Джону Сэнсому, его запрос потрясающий !
кроме того: вы должны добавить " и PT.СТОЛБЦУ ORDINAL_POSITION = КР.ORDINAL_POSITION " в конце вашего запроса.
Если у вас есть несколько полей в первичном ключе, этот оператор будет соответствовать соответствующим полям друг другу (у меня был случай, ваш запрос создал все комбинации, поэтому для 2 полей в первичном ключе у меня было 4 результата для соответствующего внешнего ключа).
(Извините, я не могу комментировать Ответ Джона, поскольку у меня недостаточно очков репутации).
этот запрос возвращает сведения о внешних ключах в таблице, он поддерживает несколько ключей столбцов.
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'
после долгого поиска я нашел рабочее решение. Моя база данных не использует 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
просто примечание для @ "John Sansom" ответ,
Если внешний ключ зависимости ищутся, я думаю, что предложение PT Where должно быть:
i1.CONSTRAINT_TYPE = 'FOREIGN KEY' -- instead of 'PRIMARY KEY'
и ON состояние:
ON PT.TABLE_NAME = FK.TABLE_NAME – instead of PK.TABLE_NAME
как обычно используется первичного ключа внешней таблицы, я думаю, что эта проблема не была замечена.
использование регулярных выражений;
SELECT COLUMN_NAME, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME
FROM KEY_COLUMN_USAGE
WHERE (table_name = *tablename*) AND NOT (REFERENCED_TABLE_NAME IS NULL)