尝试在链接表上实现级联删除,并将2个FK关系实现为父级

时间:2014-05-19 21:51:03

标签: sql-server sql-server-2008 sql-server-2008-r2

我有两张表代表

父母 - <孩子"图书馆项目"将所有记录在一个"库项目"表。为此,我使用了链接表,所以

LibraryItem- Parent -< LibraryItemLink(StdLibraryItemId_Parent)
           - Child  -< LibraryItemLink(StdLibraryItemId_Child)

我想在FK上放置级联删除,这样如果从LibraryItem中删除父记录,则删除所有关联的LibraryItemLink记录,并且如果删除任何子libraryItem记录,则同样适用。

添加约束的T-SQL是:

ALTER TABLE dbo.StdLibraryItemLink
ADD
  CONSTRAINT FK_StdLibraryItemLink_StdLibraryItem_Child FOREIGN KEY (StdLibraryItemId_Child) REFERENCES dbo.StdLibraryItem (Id) ON DELETE CASCADE,
  CONSTRAINT FK_StdLibraryItemLink_StdLibraryItem_Parent FOREIGN KEY (StdLibraryItemId_Parent) REFERENCES dbo.StdLibraryItem (Id) ON DELETE CASCADE
GO 

我得到的错误是:

Msg 1785, Level 16, State 0, Line 1
Introducing FOREIGN KEY constraint 'FK_StdLibraryItemLink_StdLibraryItem_Parent' on table 
'StdLibraryItemLink' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or 
ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
Msg 1750, Level 16, State 0, Line 1
Could not create constraint. See previous errors.

我猜这是关键点:

may cause cycles or multiple cascade paths

关于如何在两种关系上实现级联删除的建议将被理解为逻辑似乎正确,即父删除和子删除,都需要独立删除关联的链接记录。

提前致谢。

1 个答案:

答案 0 :(得分:1)

你的FK约束声明应该是

ALTER TABLE dbo.StdLibraryItemLink
ADD
  CONSTRAINT FK_StdLibraryItemLink_StdLibraryItem_Child FOREIGN KEY 
  (StdLibraryItemId_Child) REFERENCES dbo.StdLibraryItem (Id) ON DELETE CASCADE
GO 

修改

是的,SQL Server中不允许这样做。而且想一想,你会发现它毫无意义;即使您只有一个引用列,也会导致删除级联,并删除子/派生表行。多列引用同一个表的相同列(IT&#39; S OF NO BENEFIT)的重点是什么?

此外,它会被允许;你会得到一个不受欢迎的结果。为了证明这一点,我在允许的MySQL中尝试了相同的方案(供您参考,以下查询可以使用,以防您想尝试)。

父表

create table t(id int not null auto_increment primary key, `name` varchar(10));
insert into t(`name`) values('heeli'),('holi'),('heelda'); 

儿童表

create table t1(id1 int,id2 int, col varchar(10),
constraint fk1 foreign key (id1) references t(id) on delete cascade,
constraint fk2 foreign key (id2) references t(id) on delete cascade); 

insert into t1 values(1,1,'holi'),(2,2,'holi'),(2,3,'holi');

select * from t1

 id1, id2, col
'1', '1', 'holi'
'2', '2', 'holi'
'2', '3', 'holi'

从t中删除一行

delete from t where id = 2

由于t1 id1和id2都指向t id列;第二行和第三行都将被删除,这在许多情况下是不希望的结果。

select * from t1

父表中删除后t1中的结果数据

 id1, id2, col
'1', '1', 'holi'