如何在SQL Server中查找一个表被哪个外键约束引用?

202
我尝试删除一个表,但是收到如下信息:

错误消息 3726,级别 16,状态 1,行 3
无法删除对象“dbo.UserProfile”,因为它被外键约束引用。
错误消息 2714,级别 16,状态 6,行 2
数据库中已经存在名为“UserProfile”的对象。

我使用SQL Server Management Studio查找了一下,但是无法找到这个约束。如何查找外键约束?

7
我喜欢使用 sp_help 'dbo.TableName'。更多方法请参见此处:https://dev59.com/wnRB5IYBdhLWcg3w4a8o - Mark Boltuc
3
值得注意的是:@LittleSweetSeas 的答案将返回给定“引用表”的外键信息,然而@Gayathri-Varma的答案则详细介绍了给定“父表”的信息。两者在不同的上下文中都很有用,并且都各自胜出。 :-) - Izhar Aazmi
16个回答

329

这是它:

SELECT 
   OBJECT_NAME(f.parent_object_id) TableName,
   COL_NAME(fc.parent_object_id,fc.parent_column_id) ColName
FROM 
   sys.foreign_keys AS f
INNER JOIN 
   sys.foreign_key_columns AS fc 
      ON f.OBJECT_ID = fc.constraint_object_id
INNER JOIN 
   sys.tables t 
      ON t.OBJECT_ID = fc.referenced_object_id
WHERE 
   OBJECT_NAME (f.referenced_object_id) = 'YourTableName'

这样,您将获得引用表和列名。根据评论建议,已编辑为使用sys.tables而不是通用的sys.objects。谢谢,marc_s。

@marc_s:谢谢,但你能发一个例子吗?据我所知,在sys.tables中我没有FK引用。 - LittleSweetSeas
4
我的意思是:只需将“INNER JOIN sys.objects AS o ON o.OBJECT_ID = fc.referenced_object_id”替换为“INNER JOIN sys.tables t ON t.OBJECT_ID = fc.referenced_object_id”。 - marc_s
@LittleSweetSeas 我已经运行了上述查询,但仍然无法获取具有外键约束的表的对象名称和列名。 - Smart003
2
你可以通过添加更多信息来增强你的SELECT语句:SELECT f.name as 约束名称, f.type_desc as 约束类型, OBJECT_NAME(f.parent_object_id) as 受限表格, COL_NAME(fc.parent_object_id, fc.parent_column_id) as 受限列, OBJECT_NAME(f.referenced_object_id) as 引用表格, COL_NAME(fc.referenced_object_id, fc.referenced_column_id) as 引用列。 - DocOc
实际上,连接表t用于限制sys.foreign_key_columns表的输出。这可能是多余的,但这取决于您的架构。 - LittleSweetSeas
显示剩余2条评论

139

另一种方法是检查结果。

sp_help 'TableName'

(或者只需突出显示引用的TableName,然后按ALT+F1键)

随着时间的推移,我决定完善我的答案。以下是sp_help提供的结果的屏幕截图。我在此示例中使用了AdventureWorksDW2012数据库。那里有许多有用的信息,我们要找的是最后一项 - 以绿色突出显示:

在此输入图片描述


4
这提供了许多有用的信息,并且在输出底部显示外键。 - Hux
3
这使我在代码行数最少的情况下获得了很多信息。 - randow_user_1234
这是最酷的快捷方式!完全超越了使用 Ctrl-R 刷新架构! - Mr. Young
刷新本地InteliSense缓存 = Ctrl+Shift+R; Ctrl+R = 显示/隐藏结果窗格 (至少这是我的SSMS2008和SSMS2014默认设置) - Vladislav
我的朋友告诉我要锁定表名并按下Alt + F1,但这个快捷键对我不起作用。这个命令帮了我很多!谢谢 - Erga Kandly

57

试一下这个

SELECT
  object_name(parent_object_id) ParentTableName,
  object_name(referenced_object_id) RefTableName,
  name 
FROM sys.foreign_keys
WHERE parent_object_id = object_id('Tablename')

1
简洁而优雅,而且对我有用!唯一的问题是返回的 name 值是内部名称(我想),而不是父表中的实际列名。有什么解决办法吗? - Hamman Samuel
我在这里看到的是ParentTableName总是与where子句中给定的“Tablename”相同(如果包括的话)。这可能是有意为之的,并且在查询多个表时将更加有用。 - Izhar Aazmi

40

1
还有五个其他的参数可用于过滤,其中最有用的是第二个,您可以在其中指定非默认模式,例如 EXEC sp_fkeys 'Payroll','accounting' - mdisibio
1
这个帮得上忙,谢谢! - undefined
@SushiDynamite 很高兴听到这个消息。 - undefined

16

这里是查找所有数据库中外键关系最佳方法。

exec sp_helpconstraint 'Table Name'

还有一种方法

select * from INFORMATION_SCHEMA.KEY_COLUMN_USAGE where TABLE_NAME='Table Name'
--and left(CONSTRAINT_NAME,2)='FK'(If you want single key)

这个解决方案 exec sp_helpconstraint '表名' 是唯一一个对我返回任何行的。然而,约束名称是无意义的。 PRIMARY KEY (clustered) PK__org_soft__3213E83FE6B07364 - Tor
只有当您拥有足够的权限访问信息模式表时,此功能才能正常工作。 - Black

15

我正在使用此脚本查找所有与外键相关的详细信息。 我正在使用INFORMATION.SCHEMA。 以下是SQL脚本:

SELECT 
    ccu.table_name AS SourceTable
    ,ccu.constraint_name AS SourceConstraint
    ,ccu.column_name AS SourceColumn
    ,kcu.table_name AS TargetTable
    ,kcu.column_name AS TargetColumn
FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE ccu
    INNER JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc
        ON ccu.CONSTRAINT_NAME = rc.CONSTRAINT_NAME 
    INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu 
        ON kcu.CONSTRAINT_NAME = rc.UNIQUE_CONSTRAINT_NAME  
ORDER BY ccu.table_name

2
我正在寻找一种可以查看作为外键的列以及列引用的相关表的方法,这个总结得非常好。谢谢! - Nate Kindrew
这在我的一些表中缺少了一些外键,而@LittleSweetSeas的答案则显示了它们。 - Seafish

7
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;

7

如果您要通过SSMS的对象资源管理器窗口,请右键单击要删除的对象,然后选择“查看依赖项”。


5
在SQL Server管理工具中,您只需右键单击对象资源管理器中的表,然后选择“查看依赖项”。这将为您提供一个很好的起点。它显示引用该表的表、视图和存储过程。

3
在对象资源管理器中,展开表并展开“键”:

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接