SQL Server 2014:OBJECT_ID判断外键失效,EXISTS可行?求原因
为什么两种外键存在性判断的结果不同?
这个问题的核心在于**OBJECT_ID函数和sys.foreign_keys视图对约束对象的查找逻辑差异**,我来给你拆解清楚:
1. OBJECT_ID('FK', 'F')失效的原因
OBJECT_ID函数查找对象时,对约束这类依附于表的对象有特殊的名称解析要求:
- 外键约束不是独立的数据库对象,它是绑定在具体表上的。如果你只传约束名
'FK',SQL Server会在当前会话的默认架构下查找名为FK的独立对象(比如表、视图),而不会去关联表的约束列表里找。 - 正确的用法应该是指定表+约束的完整限定名称,比如
OBJECT_ID('dbo.my_table.FK', 'F')——这样SQL Server才能明确你要找的是dbo.my_table这个表上名为FK的外键约束。
你提到之前这个语句正常工作,大概率是之前的写法包含了表名(甚至架构名),后来修改时遗漏了,导致OBJECT_ID返回NULL,删除逻辑不执行。
2. sys.foreign_keys能生效的原因
sys.foreign_keys是专门存储外键约束信息的系统视图,它的name列直接记录了约束的名称(在整个数据库范围内是唯一的)。
- 当你执行
SELECT * FROM sys.foreign_keys WHERE name = 'FK'时,是直接在所有外键约束里精准匹配名称,不需要考虑所属表或架构的解析问题,所以能准确找到目标外键,触发后续的删除操作。
补充:关于sys.sysobjects的疑问
你说执行select * from dbo.sysobjects o...能返回类型为F的外键行,这是因为sys.sysobjects是兼容旧版本的系统视图,它会列出所有对象(包括约束),但OBJECT_ID函数的查找逻辑并没有跟着兼容——它还是要求你提供约束的完整限定名称才能识别,所以即使sys.sysobjects能看到,只传约束名的OBJECT_ID仍然找不到。
推荐写法
如果要判断外键是否存在,我更推荐用sys.foreign_keys的方式,它更直观可靠:
IF EXISTS( SELECT * FROM sys.foreign_keys WHERE name = 'FK') BEGIN ALTER TABLE my_table DROP CONSTRAINT [FK] END
如果坚持要用OBJECT_ID,一定要写完整的限定名称:
IF (OBJECT_ID('dbo.my_table.FK', 'F') IS NOT NULL) BEGIN ALTER TABLE my_table DROP CONSTRAINT [FK] END
内容的提问来源于stack exchange,提问作者reggaemahn
相关产品推荐
相关产品推荐

