在表“tblMaintenance”上引入 FOREIGN KEY 约束“FK2CustomerId”可能会导致循环或多个级联路径
Posted
技术标签:
【中文标题】在表“tblMaintenance”上引入 FOREIGN KEY 约束“FK2CustomerId”可能会导致循环或多个级联路径【英文标题】:Introducing FOREIGN KEY constraint 'FK2CustomerId' on table 'tblMaintenance' may cause cycles or multiple cascade paths 【发布时间】:2019-01-18 16:02:39 【问题描述】:我创建了一个与另外 2 个表有关系的表。但是当我尝试从另一个表连接 FK 时,它会显示以下警告:
在表“tblMaintenance”上引入 FOREIGN KEY 约束“FK1VehicleID”可能会导致循环或多个级联路径。指定 ON DELETE NO ACTION 或 ON UPDATE NO ACTION,或修改其他 FOREIGN KEY 约束
这是我写的:
CREATE TABLE tblMaintenance
(
MaintenanceID Int Identity(1,1) Primary Key,
Description VarChar(100),
Date Date,
TotalAmount Money,
VehicleID Int,
CustomerID Int,
PurchaseID Int,
Constraint FK2CustomerID
Foreign Key(CustomerID) References tblCustomer(CustomerID)
ON DELETE Cascade On Update Cascade,
Constraint FK1VehicleID
Foreign Key(VehicleID) References tblVehicle(VehicleID)
ON DELETE Cascade On Update Cascade,
)
Go
这是与上述声明相关的另一个声明:
--**Table tblCustomer
Create Table tblCustomer
(
CustomerID Int Identity(1,1) Primary Key,
CustomerName VarChar(30),
Address VarChar(150),
Phone VarChar(30)
)
Go
---------------End Table tblCustomer------------------------------------
--**Table tblVehicle
Create Table tblVehicle
(
VehicleID Int Identity(1,1) Primary Key,
Brand VarChar(30),
PlateNumber VarChar(30),
EngineNumber VarChar(30),
CustomerID Int,
CustomerName VarChar(30),
Constraint FK1CustomerID
ForeignKey(CustomerID) References tblCustomer(CustomerID)
On Delete Cascade On Update Cascade
)
Go
---------------End Table tblVehicle------------------------------------
【问题讨论】:
请向我们展示您使用的实际导致此警告的 T-SQL 语句 感谢您的帮助。这是我的: --**Table tblCustomer Create Table tblCustomer( CustomerID Int Identity(1,1) Primary Key, CustomerName VarChar(30), Address VarChar(150), Phone VarChar(30)) Go ------ ---------结束表 tblCustomer------------------------跨度> --**表 tblVehicle 创建表 tblVehicle( VehicleID Int Identity(1,1) 主键,品牌 VarChar(30),PlateNumber VarChar(30),EngineNumber VarChar(30) , CustomerID Int, CustomerName VarChar(30), Constraint FK1CustomerID Foreign Key(CustomerID) References tblCustomer(CustomerID) On Delete Cascade On Update Cascade ) Go ---------------End Table tblVehicle-- ---------------------------------- 抱歉,我无法在评论中换行。我是 *** 的新用户。 请不要将代码示例或示例数据放入 cmets - 因为您无法对其进行格式化,所以阅读它非常困难....而是:更新您的问题,编辑它以提供附加信息!谢谢。 【参考方案1】:早安,
在 SQL Server 中,一个表不能在由 DELETE 或 UPDATE 语句启动的所有级联引用操作的列表中出现多次。
关于完整的解释、简单的解决方法和更多信息,请访问此处的官方文档(这是上面引用的来源): https://support.microsoft.com/en-ca/help/321843/error-message-1785-occurs-when-you-create-a-foreign-key-constraint-tha
----- 更新以色列时间 2018-08-12 22:40 ------
我将尝试解释微软团队选择阻止这样的结构的原因...
假设我们有以下三个表:
DROP TABLE IF EXISTS A;
create table A (Aid NVARCHAR(3) primary key)
GO
DROP TABLE IF EXISTS B;
Create Table B(
Bid NVARCHAR(3) primary key,
Aid NVARCHAR(3)
)
Go
DROP TABLE IF EXISTS C;
Create Table C(
Cid NVARCHAR(3) primary key,
Aid NVARCHAR(3),
Bid NVARCHAR(3)
)
Go
Insert A(Aid) values ('a1'),('a2'),('a3'),('a4')
Insert B(Bid, Aid) values ('b1','a1'),('b2','a1'),('b3','a2')
Insert C(Cid,Bid, Aid) values ('c1','b1','a2'),('c2','b1','a2'),('c3','b2','a2'),('c4','b3','a4')
GO
SELECT * FROM A
SELECT * FROM B
SELECT * FROM C
GO
根据列名考虑这些表处于硬关系(使用 FOREIGN KEY)并且这些 FK 是“On Delete Cascade On Update Cascade”的情况。
-
现在让我们从表 A 中删除行 a1
既然我们从表 B 配置了 FK Cascade,那么应该删除表 B 中的相关行:这意味着应该删除行 b1、b2
但是由于表 C 对 B 有 FK,所以我们需要删除表 C 中 b1、b2 的相关行。这意味着我们删除行 c1、c2 和 c3
现在我们遇到了问题!由于表 C 也与表 A 相关,我们删除了与行 a2 相关的行 c3(我们没有删除)!现在问题提出了如何处理表 A 中的行 a2。我们删除了他的孩子,所以让我们删除它...
一秒...问题继续...现在我们删除了表A中的a2行,因此我们需要删除表B中的b3行,因此我们需要删除表C中的c4行...
理论上没有限制这样做,并继续任务直到我们完成......有数据库服务器允许这种结构。
话虽如此,当我们只想删除一行并进入删除循环时,这种情况会导致性能非常差,并且对删除的内容感到困惑。如果我们还想使用 Cascade,SQL Server 不允许这种结构设计!为了防止此类情况,SQL Server 团队选择与自动删除(On Delete Cascade)一起防止此类结构。事实上,如果你以正确的方式设计数据库,我们可能不应该达到这个要求。
注意!这种情况就是所谓的“多级联路径”,不像无限循环的情况那样极端。
注意!我在这里使用 DELETE 进行检查,但相同的问题和相同的规则也与 UPDATE 相关。如果你必须有这个结构,那么你可以删除 Cascade 并自己控制子元素的删除。
【讨论】:
感谢您的帮助。我将外键 CustomerID 放在 Table Vehicle 和 On Table Maintenance 上。之后,我在表维护上放了一个 VehicleID 的外键。我认为问题是 CustomerID 有多个删除级联更新级联到同一个表维护的路径。 这正是我给你的链接中解释的问题。考虑一下(表 A、B、C)。 B 指向 A,C 指向 A,也指向 B。如果您配置 ON DELETE Cascade,那么如果 A 中的行 X 被删除,那么 B 中的相关行(子行)也应该被删除,并且 C 中的相关行(因为两个表都指向具有 Cascade 的 A)。直到这里一切都好,但现在既然你删除了 B 中的行,你应该删除 C 中的相关行,因为 C 也指向 B。但是我们已经从 C 中删除了行,因为从 A 中删除...这种结构在 SQL Server 设计中是不允许的 顺便说一下,还有其他服务器允许这种结构。这种结构可能会出现问题,每个设计人员都可以选择如何处理这些独特的案例 - 正如 SQL Server 中提到的,微软团队选择不允许这种结构。 你的设计毫无意义。维护如何与特定客户和特定车辆相关,同时车辆与客户相关。你没看到这里可能存在的周期吗?通常与车辆相关的维护。以及与车辆相关的客户。但是您没有将客户与维护相关联!关系来自车辆。如果您需要多对多关系,您只需使用另一个关系表,但关系又是 (Maintenance-Vehicle) 和 (Vehicle-Customer) 对不起,我只有 8 个声望。我也很想给你的答案投票,但 *** 需要 15 个声望才能投票选出有用的答案。我只能检查你的答案。请你投票给我的问题好吗?我认为当有人投票我的问题时,我可能会获得更多声誉。以上是关于在表“tblMaintenance”上引入 FOREIGN KEY 约束“FK2CustomerId”可能会导致循环或多个级联路径的主要内容,如果未能解决你的问题,请参考以下文章
在表“ReservedSeats”上引入 FOREIGN KEY 约束“FK_ReservedSeats_Seats_SeatId”可能会导致循环或多个级联路径
ASP.Net MVC 3 EF“在表上引入 FOREIGN KEY 约束可能会导致循环或多个级联路径”
Python & Bigquery:使用 for 循环在表中逐行查询和插入数据
使用ajax jQuery for-each函数在表中追加多个数据