ChatGPT解决这个技术问题 Extra ChatGPT

ALTER TABLE 语句与 FOREIGN KEY 约束冲突

为什么向 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);

S
Smutje

发生这种情况是因为您尝试创建从 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);
d
dantey89

这个查询对我非常有用。它显示所有没有任何匹配的值

select FK_column from FK_table
WHERE FK_column NOT IN
(SELECT PK_column from PK_table)

在尝试查找错误条目时非常简单且非常有用。非常感谢!
D
DreamTeK

试试这个解决方案:

您的表中有一个数据项,其关联值在您希望将其用作主键表的表中不存在。使您的表为空或将关联的值添加到第二个表。


A
Ankita Biswas

可以使用 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
有一个完全合法的使用 - 如果您故意只想与某些数据建立关系,并且您被原始表格结构和内容所困扰。但这种情况确实表明原始设计存在缺陷。
Ω
ΩmegaMan

从表中删除所有现有数据,然后在表之间建立关系。


谢谢,最大。如果他们有数据,它对我有用,即使关系是完美的,Update-Database 命令也不起作用。
没有必要删除任何数据,只要它们根据正在创建的外键是有效的。
@ΩmegaMan 您正在此页面上进行编辑,没有添加任何内容并且是不必要的,因此不应进行。
s
soccer7

在将外键添加到表之前,请执行以下操作

确保表必须为空或列数据应匹配。确保它不为空。如果表格包含不去设计和更改,请手动执行。 alter table 表 1 添加外键(列名)引用表 2(列名) alter table 表 1 alter column 列名属性不为空


s
sam05

我想,外键表中的列值应该与主键表的列值匹配。如果我们试图在两个表之间创建外键约束,其中一列内的值(将成为外键)与主键表的列值不同,那么它将抛出消息。

因此,始终建议只在主键表列中存在的外键列中插入那些值。

例如。如果主表列具有值 1、2、3,并且在外键列中插入的值不同,则不会执行查询,因为它期望值介于 1 和 3 之间。


p
propoLis

尝试 DELETE tblDomare.PersNR 中的当前数据。因为 tblDomare.PersNR 中的值与 tblBana.BanNR 中的任何值都不匹配。


@agenc 我回答你的问题了吗?
b
belka

当您在表 B 中定义引用表 A 的主键的外键时,这意味着当值在 B 中时,它必须在 A 中。这是为了防止对表的不一致修改。

在您的示例中,您的表包含:

带有 PRIMARY KEY (PersNR) 的 tblDomare:

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 中添加带有 BanNR 的行(6811034679、7606091347、8508284163)

或删除 tblDomare 中与 tblBana 没有对应关系的所有行(但您的表将为空)

一般建议:您应该在填充表之前有外键约束。外键在这里是为了防止表的用户填写不一致的表。


“您的错误是因为您在 tblDomare 中插入了行,而在 tblBana 中没有对应关系。”就是这样!
R
Ralph B. Roman

用非常简单的话来说,您的表中已经存在数据,并且您尝试与之创建关系的表确实为已经存在的值设置了该主键。

要么删除现有表的所有值。在新表中添加所有外键引用的值。


a
ako

我也遇到了这个错误,因为 Smutje 引用了确保您的基本外键表的外键列中没有不在参考表中的值,即(基本外键表中的每个值(列的值是外键)也必须在您的参考表列中)最好先清空基本外键表然后设置外键


A
Ataur Rahman Munna

您输入的数据表(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);

g
greg

Smutje 是正确的,Chad HedgeCock 提供了一个伟大的外行的例子。我想以乍得的例子为基础,提供一种查找/删除这些记录的方法。我们将使用 Customer 作为父级,使用 Order 作为子级。 CustomerId 是通用字段。

select * from Order Child 
left join Customer Parent on Child.CustomerId = Parent.CustomerId
where Parent.CustomerId is null 

如果你正在阅读这个线程......你会得到结果。这些是孤儿。 select * from Order Child left join Customer Parent on Child.CustomerId = Parent.CustomerId where Parent.CustomerId 为空 注意右下角的行数。

去验证你要删除这些行的任何人!

begin tran 
delete Order
from Order Child 
left join Customer Parent on Child.CustomerId = Parent.CustomerId
where Parent.CustomerId is null 

运行第一个位。检查行数=您的预期

提交 tran

commit tran 

当心。有人草率的编程让你陷入了这个混乱。在删除孤儿之前,请确保您了解原因。也许父母需要恢复。


谢谢回复。我正在使用 stackoverflow 数据库(实际上是 gamedev),当我与用户 LEFT JOIN 徽章时发现了两个 NULL。难怪约束不起作用......
V
VJPPaz

从我们的角度来看,这是场景:

我们在数据库中有一个包含记录的现有表。然后我引入了一个不可为空的外键执行更新后我得到了这个错误。

你问我是怎么解决的?

解决方案:我刚刚删除了表的所有记录,然后尝试更新数据库,并且成功。


W
Willy David Jr

这发生在我身上,因为我正在设计我的数据库,我注意到我在主表上更改了我的种子,现在关系表在主表上没有外键。

所以我需要截断两个表,它现在可以工作了!


a
adrianex03

您应该查看您的表是否在行上有任何数据。如果“是”,那么您应该截断表,否则您可以使它们在 tblDomare.PersNRtblBana.BanNR 处具有相同数量的数据并进行虎钳。


j
jeromej

在我的场景中,使用 EF,在尝试在现有数据上创建这个新的外键时,我错误地尝试在创建外键后填充数据(创建链接)。

解决方法是在创建外键之前填充您的数据,因为它会检查所有外键以查看链接是否确实有效。所以如果你还没有填充它,它就不可能工作。


M
Metin Atalay

我在我的项目中遇到了一些问题。

https://i.stack.imgur.com/gN6US.png

在子表中,没有任何记录 ID 等于 1 和 11

https://i.stack.imgur.com/GVrU3.png

我插入了 ID 等于 1 和 11 的 DEAL_ITEM_THIRD_PARTY_PO 表,然后我可以创建 FK


M
M Arslan Riaz

请先从该表中删除数据,然后再次运行迁移。你会获得成功


A
Ahmed Hafiz

我有同样的问题。我的问题是 nullable: true in column (migration file):

AddColumn("dbo.table", "column", c => c.Int(nullable: true));
        

可能的解决方案:

将可为空的“假”更改为“真”。 (不推荐)将属性类型从 int 更改为 int? (推荐的)

如果需要,稍后在添加列 > 然后在以前的记录中缺少字段数据后进行更改

如果您已将现有属性从可空更改为不可空: 3) 填写数据库记录中的列数据


G
Golden Lion

子表中的外键约束必须有一个带有主键的父表。主键必须是唯一的。外键值必须与专利表主键中的值匹配


A
Amara Miloudi

当您将表列从可为空的列更改为该列是外键的不可为空的列时,您必须:

首先,用值初始化该列(因为它是不可为空的外键)。之后,您可以正常更改表格列。


R
RainyTears

请尝试以下查询:

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

d
desertnaut

或者你可以使用这个

SELECT  fk_id FROM dbo.tableA
Except
SELECT fk_id From dbo.tableB

D
Doug Boude

仅供参考,以防您进行所有数据引用检查并且没有发现错误数据……显然,不可能在两个表和字段之间创建外键约束,其中这些字段是两个表中的主键!不要问我是怎么知道的。