为什么SQL Server阻止我创建这些外键?

时间:2011-03-31 13:42:13

标签: sql-server sql-server-2005

我的(删节)架构有(或者更确切地说,需要)以下表格和关系:

Clients (ID INT PRIMARY KEY)
Files (
    ID INT PRIMARY KEY,
    Client INT REFERENCES Clients(ID) ON DELETE CASCADE)
Interfaces (
    ID INT PRIMARY KEY,
    Client INT REFERENCES Clients(ID) ON DELETE CASCADE)
Files_Interfaces (
    "File" INT REFERENCES Files(ID) ON DELETE CASCADE,
    Interface INT REFERENCES Interfaces(ID) ON DELETE CASCADE)

从这个架构中可以看出,客户端可以有多个文件和多个接口。接口和文件之间存在多对多关系(因此联结表Files_Interfaces),唯一的层次关系是客户端(从ClientsFiles之间存在一对多的关系InterfacesFiles_Interfaces)。

我需要FilesInterfaces以及Files_Interfaces之间的这些约束,这样,如果删除文件或界面,所有相关的关联都会被销毁。

问题是,SQL Server 2005不会让我拥有这个架构。当我尝试使用这些约束创建Files_Interfaces时,我收到以下错误:

  

引入FOREIGN KEY约束   'FK__Files_Int__Inter__3D2915A8'开启   表'Files_Interfaces'可能会导致   循环或多个级联路径。   指定ON DELETE NO ACTION或ON   更新无动作,或修改其他动作   FOREIGN KEY约束。

是什么给出的?是因为如果我删除了一个客户端,那么这两个文件和接口都会被删除,那么{{1}}个记录有两个很好的理由消失吗?如果是这样,为什么这是一件坏事?

我可以以某种方式防止此错误吗?

1 个答案:

答案 0 :(得分:5)

虽然理论上多个级联路径(甚至是循环)没有任何问题,但实施它们可能很难。

就像现在一样,SQL Server要求级联图应该是树而不是有向无环(甚至更糟,循环)图:

  

由单个DELETEUPDATE触发的一系列级联引用操作必须形成一个不包含循环引用的树。在DELETEUPDATE生成的所有级联参照操作的列表中,任何表都不会出现多次。此外,级联引用操作树不得包含任何指定表的多个路径。树的任何分支在遇到已指定NO ACTION的表或默认值时都会结束。

由于实现限制,SQL Server不会将级联删除优化为单个基于集合的操作,而是将树拆分为一系列单独的连接。如果是A -> B -> C,则DELETE A不是DELETE A JOIN B JOIN C,而是DELETE A JOIN B OUTPUT B_temp,后跟DELETE B_temp JOIN C

如果有多个级联路径,则会导致多个B_temp