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.PersNRtblBana.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.PersNRtblBana.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`

MySQL的多表设计

EJB3.x异常:Unsuccessful: alter table ORDER add constraint FK47F8F2EFC558D0A foreign key (ORDER_USR_ID)

如何用oracle里面的alter table语句去添加一个列约束

mysql添加外键语句

ERROR 1215 (HY000): Cannot add foreign key constraint