Đây là một truy vấn đơn giản để khớp các khóa ngoại với các bảng / cột được tham chiếu của chúng:
SELECT
o1.name AS FK_table,
c1.name AS FK_column,
fk.name AS FK_name,
o2.name AS PK_table,
c2.name AS PK_column,
pk.name AS PK_name,
fk.delete_referential_action_desc AS Delete_Action,
fk.update_referential_action_desc AS Update_Action
FROM sys.objects o1
INNER JOIN sys.foreign_keys fk
ON o1.object_id = fk.parent_object_id
INNER JOIN sys.foreign_key_columns fkc
ON fk.object_id = fkc.constraint_object_id
INNER JOIN sys.columns c1
ON fkc.parent_object_id = c1.object_id
AND fkc.parent_column_id = c1.column_id
INNER JOIN sys.columns c2
ON fkc.referenced_object_id = c2.object_id
AND fkc.referenced_column_id = c2.column_id
INNER JOIN sys.objects o2
ON fk.referenced_object_id = o2.object_id
INNER JOIN sys.key_constraints pk
ON fk.referenced_object_id = pk.parent_object_id
AND fk.key_index_id = pk.unique_index_id
ORDER BY o1.name, o2.name, fkc.constraint_column_id
Đầu ra có tám cột: tên bảng và cột cho các khóa ngoại (FK_table, FK_column), tên của các ràng buộc khóa ngoài (FK_name), PK được tham chiếu hoặc tên chỉ mục duy nhất và tên cột (PK_table, PK_column), tên của PK được tham chiếu hoặc chỉ mục duy nhất (PK_name) và các hành động cập nhật / xóa tầng (Delete_Action, Update_Action).
(Đã chỉnh sửa để thêm một số cột đầu ra.)
EDIT: Tôi trở lại 6 năm sau với phiên bản cải tiến này. Tôi nhận ra rằng truy vấn ban đầu không thực sự xử lý tốt các khóa ngoại nhiều cột và tôi cũng muốn có thể nhanh chóng xác định các khóa ngoại bị vô hiệu hóa, không tin cậy hoặc không bị khóa. Vì vậy, đây là phiên bản mới sửa chữa tất cả điều đó.
Các khóa nhiều cột được hiển thị dưới dạng danh sách được phân tách bằng dấu phẩy trong FK_columns
và PK_columns
, bằng cách sử dụng truyền thống FOR XML
/ STUFF
lạm dụng. Các FK_indexes
chương trình cột tên của bất kỳ chỉ số trên bàn nước ngoài quan trọng mà khả năng có thể được sử dụng để thỏa mãn tìm kiếm bằng cách sử dụng các cột khóa ngoài (chủ yếu là để tối ưu hóa xóa hoặc cập nhật vào bảng khóa chính). Nếu vậy NULL
, thì bạn đã có một khóa ngoại chưa được giải thích. Bạn có thể điều chỉnh ORDER BY
hoặc thêm một WHERE
mệnh đề (nhận xét bên dưới) nếu bạn muốn sắp xếp theo tên bảng PK, bộ lọc cho các bảng PK / FK cụ thể, v.v.
SELECT
fk.is_disabled,
fk.is_not_trusted,
OBJECT_SCHEMA_NAME(o1.object_id) AS FK_schema,
o1.name AS FK_table,
--Generate list of columns in referring side of foreign key
STUFF(
(
SELECT ', ' + c1.name AS [text()]
FROM sys.columns c1 INNER
JOIN sys.foreign_key_columns fkc
ON c1.object_id = fkc.parent_object_id
AND c1.column_id = fkc.parent_column_id
WHERE fkc.constraint_object_id = fk.object_id
FOR XML PATH('')
), 1, 2, '') AS FK_columns,
--Look for any indexes that will fully satisfy the foreign key columns
STUFF(
(
SELECT ', ' + i.name AS [text()]
FROM sys.indexes i
WHERE i.object_id = o1.object_id
AND NOT EXISTS ( --Find foreign key columns that don't match the index key columns
SELECT fkc.constraint_column_id, fkc.parent_column_id
FROM sys.foreign_key_columns fkc
WHERE fkc.constraint_object_id = fk.object_id
EXCEPT
SELECT ic.key_ordinal, ic.column_id
FROM sys.index_columns ic
WHERE ic.object_id = i.object_id AND ic.index_id = i.index_id
)
FOR XML PATH('')
), 1, 2, '') AS FK_indexes,
fk.name AS FK_name,
OBJECT_SCHEMA_NAME(o2.object_id) AS PK_schema,
o2.name AS PK_table,
--Generate list of columns in referenced (i.e. PK) side of foreign key
STUFF(
(
SELECT ', ' + c2.name AS [text()]
FROM sys.columns c2
INNER JOIN sys.foreign_key_columns fkc
ON c2.object_id = fkc.referenced_object_id
AND c2.column_id = fkc.referenced_column_id
WHERE fkc.constraint_object_id = fk.object_id
FOR XML PATH('')
), 1, 2, '') AS PK_columns,
pk.name AS PK_name,
fk.delete_referential_action_desc AS Delete_Action,
fk.update_referential_action_desc AS Update_Action
FROM sys.objects o1
INNER JOIN sys.foreign_keys fk
ON o1.object_id = fk.parent_object_id
INNER JOIN sys.objects o2
ON fk.referenced_object_id = o2.object_id
INNER JOIN sys.key_constraints pk
ON fk.referenced_object_id = pk.parent_object_id
AND fk.key_index_id = pk.unique_index_id
--WHERE o2.name = 'Company_Address'
ORDER BY o1.name, o2.name