SQL Server创建外键报错:被引用表无匹配主键或候选键
问题报错
创建外键时触发如下SQL Server错误:
Msg 1776, Level 16, State 0, Line 1
There are no primary or candidate keys in the referenced table 'dbo.QLKeSach' that match the referencing column list in the foreign key 'fk_QLKeSach_QLKeSach'.
Msg 1750, Level 16, State 0, Line 1
Could not create constraint. See previous errors.
外键创建失败原因
触发Msg 1776错误的核心规则是:SQL Server 中创建外键约束时,被引用表的关联列必须是主键,或是配置了唯一约束的候选键,普通非空列不能作为外键的关联目标。
结合提供的脚本,具体问题点有3个:
- 要关联的被引用表
dbo.QLTangSach的MaTang字段没有设置主键或唯一约束,不满足外键创建的前置要求,这是报错的直接原因。 - 现有表结构存在循环关联的逻辑错误:书架表
QLKeSach存储了所属楼层IDMaTang,楼层表QLTangSach又存储了书架IDMaKeSach,不符合“楼层包含书架”的正常业务层级关系。 - 建表语句最后一个字段末尾多了冗余逗号,部分SQL Server版本会直接触发语法错误,导致表创建失败。另外报错中提到的
fk_QLKeSach_QLKeSach是之前误操作残留的自引用外键(外键指向当前表自身的列),因为当前表也没有对应主键,同样会触发报错。
解决方法
方法1:重新构建符合规范的表结构(推荐)
先清理已存在的错误表和残留约束,再按照主从表顺序创建表、配置主键,最后创建外键:
-- 清理残留的错误约束和表 ALTER TABLE dbo.QLKeSach DROP CONSTRAINT IF EXISTS fk_QLKeSach_QLKeSach, fk_QLKeSach; IF OBJECT_ID('dbo.QLKeSach', 'U') IS NOT NULL DROP TABLE dbo.QLKeSach; IF OBJECT_ID('dbo.QLTangSach', 'U') IS NOT NULL DROP TABLE dbo.QLTangSach; -- 先创建父表:楼层表,将唯一标识MaTang设为主键 CREATE TABLE QLTangSach ( MaTang varchar(10) NOT NULL PRIMARY KEY, TenTang char(30) NOT NULL -- 移除楼层表中不合理的MaKeSach字段,楼层作为书架的上级实体,不需要存储下属书架ID ) -- 再创建子表:书架表,将唯一标识MaKeSach设为主键 CREATE TABLE QLKeSach ( MaKeSach varchar(10) NOT NULL PRIMARY KEY, TenKeSach char(10) NOT NULL, MaTang varchar(10) NOT NULL, MaNgan varchar(10) NOT NULL, MaKho varchar(10) NOT NULL -- 移除末尾多余的逗号 ) -- 最后创建外键约束 ALTER TABLE dbo.QLKeSach ADD CONSTRAINT fk_QLKeSach_MaTang FOREIGN KEY (MaTang) REFERENCES dbo.QLTangSach(MaTang);
方法2:在已有表上补全约束(适合已有测试数据不想删表的场景)
如果两张表已经录入了测试数据,不需要删表重建,先给被引用表的关联列补主键/唯一约束,再创建外键即可:
- 先清理残留的错误约束:
ALTER TABLE dbo.QLKeSach DROP CONSTRAINT IF EXISTS fk_QLKeSach_QLKeSach, fk_QLKeSach;
- 给
QLTangSach表的MaTang列添加主键约束(执行前需确认MaTang列没有重复值、没有NULL值):
ALTER TABLE dbo.QLTangSach ADD CONSTRAINT PK_QLTangSach_MaTang PRIMARY KEY (MaTang);
- 执行外键创建语句即可成功:
ALTER TABLE dbo.QLKeSach ADD CONSTRAINT fk_QLKeSach FOREIGN KEY (MaTang) REFERENCES dbo.QLTangSach(MaTang);
注意:如果后续要建立书架和其他子表(比如格子表、仓库表)的关联,也需要先给父表的关联字段设置主键/唯一约束,再创建外键。
内容的提问来源于stack exchange,提问作者Triet Vo
相关产品推荐
相关产品推荐

