如何在没有ON DELETE级联的情况下删除(冲突REFERENCE约束)



我有一个巨大的遗留数据库,其中有一个表,它有多个指向另一个表的外键,而且看不到任何级联,类似于下面的示例表:

create table Users (
Id int primary key identity,
Name varchar(max)
)
create table Products (
Id int primary key identity,
Name varchar(max),
CreatedBy int foreign key references Users(Id),
UpdatedBy int foreign key references Users(Id)
)
insert into Users values('Bar')
insert into Users values('Baz')
insert into Products values('Foo', 1, 2)

我需要能够删除一些旧数据,但它当然会抛出引用异常:

delete from Users where Name='Bar'

DELETE语句与REFERENCE约束"FK__Products_Create__1AD3FDA4"冲突。冲突发生在数据库"Foo"、表"dbo.Products"、列"CreatedBy"中。


由于数据库的复杂性,我无法预先删除所有引用,所以我试图通过设置级联来以编程方式添加临时外键。然而,对于这个具有多个外键的特定表,这会导致第二个UpdatedByalter:上的cycles or multiple cascade paths

alter table Products add foreign key (CreatedBy) references Users(Id) on delete cascade
alter table Products add foreign key (UpdatedBy) references Users(Id) on delete cascade

在表"Products"上引入FOREIGN KEY约束"FK__Products_Update_1DB06A4F"可能会导致循环或多个级联路径。指定ON DELETE NO ACTION或ON UPDATE NO ACTION,或修改其他FOREIGN KEY约束。


如何在保持引用完整性的同时使delete from Users where工作,无论是通过某种方式解决多个级联路径问题还是其他方式?

就我个人而言,我不会这么做(我会预先删除所有引用的数据,并手动检查完整性)。请参阅:是否可以使用T-SQL临时禁用外键约束?

报价:

-- disable all constraints
EXEC sp_msforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT all"

一旦禁用了约束,请删除数据,但请记住在禁用后再次打开它们!

-- enable all constraints
EXEC sp_msforeachtable @command1="print '?'", @command2="ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all"

还要注意,存储过程sp_msforeachtable没有文档,可能会在SQL Server的未来版本中消失。

如果您不想全面禁用约束(也许您有一个应用表的列表),那么只需禁用它们,正如您在上面的代码中看到的那样。

ALTER TABLE [Products] NOCHECK CONSTRAINT ALL
DELETE FROM [Users] where Name='Bar'
ALTER TABLE [Products] WITH CHECK CHECK CONSTRAINT ALL

所有的功劳都归于克里斯托夫的回答。请投票!

相关内容

最新更新