我有一个巨大的遗留数据库,其中有一个表,其中有多个外键指向另一个表,并且看不到一个级联,类似于下面的示例表:
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'。
由于数据库的复杂性,我无法预先删除所有引用,因此我尝试以编程方式添加临时外键,并设置级联来解决它们。但是,对于具有多个外键到另一个表的特定表,这会在第二个cycles or multiple cascade paths
上生成UpdatedBy
更改:
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
在保持参照完整性的同时工作?
答案 0 :(得分:1)
我个人不会这样做(我会预先删除所有引用的数据并手动检查完整性)。请参阅:Can foreign key constraints be temporarily disabled using 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
所有功劳都归kristof's answer所有。请投票!