ALTER TABLE 语句与 FOREIGN KEY 约束冲突
Posted
技术标签:
【中文标题】ALTER TABLE 语句与 FOREIGN KEY 约束冲突【英文标题】:The ALTER TABLE statement conflicted with the FOREIGN KEY constraint 【发布时间】:2014-03-17 08:28:04 【问题描述】:为什么在tblDomare
表中添加外键会导致这个错误?
ALTER TABLE 语句与 FOREIGN KEY 约束“FK__tblDomare__PersN__5F7E2DAC”冲突。冲突发生在数据库“almu0004”、表“dbo.tblBana”、列“BanNR”中。
代码
CREATE TABLE tblDomare
(PersNR VARCHAR (15) NOT NULL,
fNamn VARCHAR (15) NOT NULL,
eNamn VARCHAR (20) NOT NULL,
Erfarenhet VARCHAR (5),
PRIMARY KEY (PersNR));
INSERT INTO tblDomare (PersNR,fNamn,eNamn,Erfarenhet)
Values (6811034679,'Bengt','Carlberg',10);
INSERT INTO tblDomare (PersNR,fNamn,eNamn,Erfarenhet)
Values (7606091347,'Josefin','Backman',4);
INSERT INTO tblDomare (PersNR,fNamn,eNamn,Erfarenhet)
Values (8508284163,'Johanna','Backman',1);
CREATE TABLE tblBana
(BanNR VARCHAR (15) NOT NULL,
PRIMARY KEY (BanNR));
INSERT INTO tblBana (BanNR)
Values (1);
INSERT INTO tblBana (BanNR)
Values (2);
INSERT INTO tblBana (BanNR)
Values (3);
ALTER TABLE tblDomare
ADD FOREIGN KEY (PersNR)
REFERENCES tblBana(BanNR);
【问题讨论】:
【参考方案1】:发生这种情况是因为您尝试创建一个从 tblDomare.PersNR
到 tblBana.BanNR
的外键,但是/并且 tblDomare.PersNR
中的值与 tblBana.BanNR
中的任何值都不匹配。您不能创建违反参照完整性的关系。
【讨论】:
这对我来说是答案,但我仍然很难意识到问题出在哪里,所以我将举一个外行的例子。如果您有一个名为“Orders”的表和一个名为“Customers”的表,并且您删除了一些旧客户,但没有删除他们的订单,如果您决定将外键从 Orders.CustomerId 设置为 Customers,您将收到此错误。ID。有些订单已经没有对应的客户了,所以无法添加外键。 这是一个检查错误值的查询: select distinct referrerTable.referenceColumn from referrerTable left join referrerTable on referrerTable.referenceColumn = referrerTable.referenceColumn where referrerTable.referenceColumn is null; 在紧要关头,您还可以使用“ALTER TABLE tablename WITH NOCHECK ...”选项来添加 FK。这将允许您添加关系,即使现有数据破坏了约束。首先清理数据显然更好,但这至少为您提供了另一种选择。 @DaveInMaine 如果有人“在需要时”停用数据库约束,我会问为什么一开始就用它们来麻烦自己,而不是在对数据库完整性不感兴趣的情况下简单地跳过它们。 @Sinjai 例如在执行INSERT INTO tblDomare (PersNR,fNamn,eNamn,Erfarenhet) Values (8508284163,'Johanna','Backman',1);
之前,必须在 tblBana 中插入相应的条目:INSERT INTO tblBana (BanNR) Values (8508284163);
【参考方案2】:
这个查询对我非常有用。它显示所有没有任何匹配项的值
select FK_column from FK_table
WHERE FK_column NOT IN
(SELECT PK_column from PK_table)
【讨论】:
在尝试查找错误条目时非常简单且非常有用。非常感谢!【参考方案3】:试试这个解决方案:
您的表中有一个数据项,其关联值在您希望将其用作主键表的表中不存在。 使您的表为空或将关联的值添加到第二个表。
【讨论】:
【参考方案4】:可以使用 ALTER TABLE tablename WITH NOCHECK ... 创建外键,这将允许违反外键的数据。
“ALTER TABLE tablename WITH NOCHECK ...”选项来添加 FK——这个解决方案对我有用。
【讨论】:
请注意,允许此类违规行为会破坏外键约束的目的。 危险的...!!!仅当您不想丢失表中当前的数据时才应使用。但即便如此,为什么不进行备份,然后删除无效的 ID。 我需要通过 java/spring/code 来实现,而不是直接通过 SQL 查询,任何想法如何使用以下代码来做到这一点:@ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.DETACH) @JoinTable(name = "tbUsuariosTipoOcorrencia", joinColumns = @JoinColumn(name = "idUsuario") , inverseJoinColumns = @JoinColumn(name = "idTipoOcorrencia") )
我这样做是通过数据库解决的查询:alter table tbUsuariosTipoOcorrencia WITH NOCHECK add constraint FKnbxg3ua7b8c5d53wps69q6jh foreign key (idUsuario) references tbUsuarios
【参考方案5】:
我猜,外键表中的列值应该与主键表的列值匹配。如果我们试图在两个表之间创建一个外键约束,其中一列中的值(将成为外键)与主键表的列值不同,那么它将抛出该消息。
因此,始终建议只在主键表列中存在的外键列中插入那些值。
例如。如果主表列具有值 1、2、3,并且在外键列中插入的值不同,则不会执行查询,因为它期望值介于 1 和 3 之间。
【讨论】:
【参考方案6】:在向表中添加外键之前,请执行以下操作
-
确保表必须为空或列数据应匹配。
确保它不为空。
如果表格包含不去设计和更改,请手动进行。
alter table 表1添加外键(列名)引用表2(列名)
alter table 表1 alter column Column Name 属性不为空
【讨论】:
【参考方案7】:从表中删除所有现有数据,然后在表之间建立关系。
【讨论】:
谢谢,最大。如果他们有数据,它对我有用,即使关系是完美的,Update-Database 命令也不起作用。 没有必要删除任何数据,只要它们根据正在创建的外键是有效的。 @ΩmegaMan 您正在此页面上进行编辑,没有添加任何内容,因此不应该进行。【参考方案8】:尝试DELETE
来自tblDomare.PersNR
的当前数据。因为tblDomare.PersNR
中的值与tblBana.BanNR
中的任何值都不匹配。
【讨论】:
@agenc 我回答你的问题了吗?【参考方案9】:当你在表 B 中定义一个外键引用表 A 的主键时,这意味着当一个值在 B 中时,它必须在 A 中。这是为了防止对表的不一致修改。
在您的示例中,您的表格包含:
tblDomare 与 PRIMARY KEY (PersNR)
:
PersNR |fNamn |eNamn |Erfarenhet
-----------|----------|-----------|----------
6811034679 |'Bengt' |'Carlberg' |10
7606091347 |'Josefin' |'Backman' |4
8508284163 |'Johanna' |'Backman' |1
---------------------------------------------
tblBana:
BanNR
-----
1
2
3
-----
此声明:
ALTER TABLE tblDomare
ADD FOREIGN KEY (PersNR)
REFERENCES tblBana(BanNR);
表示tblDomare
中任何带有键PersNR
的行必须在表tblBana
中与键BanNR
有对应关系。您的错误是因为您在 tblDomare
中插入了行,而在 tblBana
中没有对应关系。
2 个解决方案来解决您的问题:
在tblBana
中添加行,在 (6811034679、7606091347、8508284163) 中添加 BanNR
或删除tblDomare
中与tblBana
没有对应关系的所有行(但您的表格将是空的)
一般建议:在填充表之前,您应该有外键约束。外键在这里是为了防止表的用户填写不一致的表。
【讨论】:
"您的错误是因为您在 tblDomare 中插入了行,而在 tblBana 中没有对应关系。"就是这样!【参考方案10】:我也有这个错误 正如 Smutje 所引用的,确保您的基本外键表的外键列中没有不在参考表中的值,即(基本外键表中的每个值(作为外键的列的值)也必须在您的参考表列中) 最好先清空基本外键表然后设置外键
【讨论】:
【参考方案11】:Smutje 是正确的,Chad HedgeCock 提供了一个伟大的外行的例子。 我想以乍得的例子为基础,提供一种查找/删除这些记录的方法。 我们将使用 Customer 作为父级,使用 Order 作为子级。 CustomerId 是通用字段。
select * from Order Child
left join Customer Parent on Child.CustomerId = Parent.CustomerId
where Parent.CustomerId is null
如果您正在阅读此主题...您将获得结果。这些是孤儿。从订单子中选择 * 在 Child.CustomerId = Parent.CustomerId 上左加入客户父级 其中 Parent.CustomerId 为 null 请注意右下角的行数。
与您需要的任何人确认您将删除这些行!
begin tran
delete Order
from Order Child
left join Customer Parent on Child.CustomerId = Parent.CustomerId
where Parent.CustomerId is null
运行第一个位。 检查行数 = 你的预期
提交翻译
commit tran
小心。有人草率的编程让你陷入了这个混乱。在删除孤儿之前,请确保您了解原因。也许父母需要恢复。
【讨论】:
感谢您的回复。我正在使用 *** 数据库(实际上是 gamedev),当我与用户 LEFT JOIN 徽章时发现了两个 NULL。难怪约束不起作用......【参考方案12】:在我们看来,情况是这样的:
-
我们在数据库中有一个包含记录的现有表。
然后我介绍一个不可为空的外键
执行更新后出现此错误。
我是怎么解决你的问题的?
解决方案:我刚刚删除了表的所有记录,然后尝试更新数据库,成功了。
【讨论】:
【参考方案13】:您输入的数据表(tbldomare)与您分配主键表的数据不匹配。在 tbldomare 之间写入并添加这个词(不带检查)然后执行你的代码。
例如,您输入了一个表格 tbldomar 这个数据
INSERT INTO tblDomare (PersNR,fNamn,eNamn,Erfarenhet)
Values (6811034679,'Bengt','Carlberg',10);
并且您分配了一个 foreign key
表以仅接受 1,2,3
。
您有两种解决方案,一种是删除您输入表格的数据,然后执行代码。另一个是写这个词(没有检查)把它放在你的表名之间并添加 像这样
ALTER TABLE tblDomare with nocheck
ADD FOREIGN KEY (PersNR)
REFERENCES tblBana(BanNR);
【讨论】:
【参考方案14】:这发生在我身上,因为我正在设计我的数据库,我注意到我在主表上更改了我的种子,现在关系表在主表上没有外键。
所以我需要截断两个表,现在它可以工作了!
【讨论】:
【参考方案15】:您应该查看您的表中的行是否有任何数据。如果“是”,那么您应该截断表,否则您可以使它们在tblDomare.PersNR
到tblBana.BanNR
和虎钳上具有相同数量的数据。
【讨论】:
【参考方案16】:在我的场景中,使用 EF,在尝试在现有数据上创建此新外键时,我错误地尝试在创建外键后填充数据(创建链接)。
解决方法是在创建外键之前填充您的数据,因为它会检查所有外键以查看链接是否确实有效。所以如果你还没有填充它,它就不可能工作。
【讨论】:
【参考方案17】:我在项目中遇到了一些问题。
在子表中,没有任何ID等于1和11的记录
我插入了 ID 等于 1 和 11 的 DEAL_ITEM_THIRD_PARTY_PO 表,然后我可以创建 FK
【讨论】:
【参考方案18】:请先从该表中删除数据,然后再次运行迁移。你会成功的
【讨论】:
【参考方案19】:简单来说,您的表中已经存在数据,并且您尝试与之建立关系的表确实为已经存在的值设置了 主键。
-
要么删除现有表的所有值。
在新表中添加所有外键引用的值。
【讨论】:
【参考方案20】:我遇到了同样的问题。 我的问题是 nullable: true 在列(迁移文件):
AddColumn("dbo.table", "column", c => c.Int(nullable: true));
可能的解决方案:
-
将可为空的“假”更改为“真”。 (不推荐)
将属性类型从
int
更改为 int?
(推荐)
如果需要,稍后在添加列后更改此设置 > 然后在以前的记录中缺少字段数据
如果您已将现有属性从可空更改为不可空: 3) 填写数据库记录中的列数据
【讨论】:
【参考方案21】:子表中的外键约束必须有一个带有主键的父表。主键必须是唯一的。外键值必须匹配专利表主键中的值
【讨论】:
【参考方案22】:当您将表列从可为空的列更改为该列是外键的不可为空的列时,您必须:
首先,用值初始化这个列(因为它是外来的 键不可为空)。
之后,您可以正常更改表格列。
【讨论】:
【参考方案23】:请尝试以下查询:
CREATE TABLE tblBana
(BanNR VARCHAR (15) NOT NULL PRIMARY KEY,
);
CREATE TABLE tblDomare
(PersNR VARCHAR (15) NOT NULL PRIMARY KEY,
fNamn VARCHAR (15) NOT NULL,
eNamn VARCHAR (20) NOT NULL,
Erfarenhet VARCHAR (5),
FK_tblBana_Id VARCHAR (15) references tblBana (BanNR)
);
INSERT INTO tblBana (BanNR)
Values (3);
INSERT INTO tblDomare (PersNR,fNamn,eNamn,Erfarenhet,FK_tblBana_Id)
Values (8508284173,'Johanna','Backman',1,3);
【讨论】:
【参考方案24】:或者你可以使用这个
SELECT fk_id FROM dbo.tableA
Except
SELECT fk_id From dbo.tableB
【讨论】:
【参考方案25】:仅供参考,以防您进行所有数据引用检查并且没有发现错误数据...显然,不可能在两个表和字段之间创建外键约束,其中这些字段是两者的主键表!不要问我怎么知道的。
【讨论】:
以上是关于ALTER TABLE 语句与 FOREIGN KEY 约束冲突的主要内容,如果未能解决你的问题,请参考以下文章
SQL:alter table`familymembers`在laravel中添加约束`familymembers_user_id_foreign`外键(`user_id`)引用`all_users`
EJB3.x异常:Unsuccessful: alter table ORDER add constraint FK47F8F2EFC558D0A foreign key (ORDER_USR_ID)