Sql server 如何在不使用删除级联的情况下删除(冲突引用约束)

Sql server 如何在不使用删除级联的情况下删除(冲突引用约束),sql-server,tsql,cascading-deletes,Sql Server,Tsql,Cascading Deletes,我有一个巨大的遗留数据库,其中有一个表,该表有多个外键指向另一个表,并且没有一个级联可见,类似于下面的示例表: 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 refer

我有一个巨大的遗留数据库,其中有一个表,该表有多个外键指向另一个表,并且没有一个级联可见,类似于下面的示例表:

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语句与引用约束“FK__产品__创建__1AD3FDA4”冲突。冲突发生在数据库“Foo”、表“dbo.Products”、列“CreatedBy”中


由于数据库的复杂性,我无法预先删除所有引用,因此我尝试通过编程方式添加临时外键,并设置级联来解析它们。但是,对于具有多个外键到另一个表的特定表,这将导致第二个
更新的
循环或多个级联路径

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”上引入外键约束“FK__Products__Update__1DB06A4F”可能会导致循环或多个级联路径。指定“在删除时不执行操作”或“在更新时不执行操作”,或修改其他外键约束



我如何才能使
工作的用户中删除,同时保持引用完整性,无论是通过某种方式绕过多个级联路径问题还是其他方式?

我个人不会这样做(我会预先删除所有引用数据并手动检查完整性)。见:

引述:

-- 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"
还请注意,存储过程spmsforeachtable
没有文档记录,可能会在SQL Server的未来版本中消失

如果您不希望覆盖禁用约束(也许您有一个应用的表列表),那么只需禁用它们,正如您在上面的代码中所看到的

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

所有的功劳都归于他。请投票

谢谢,正如OP predeleting references中提到的,db并不是一个真正的选项,它绝对是巨大的,而且它不是生产功能,不需要投入大量的资源来单步遍历数百个表。我不想禁用所有的约束检查,因为我希望所有与删除的用户相关的垃圾也被删除,而不是挂在无参考的地方。考虑下面的内容:您想删除用户<代码> ID=3 < /COD>。有一个产品由该用户创建,并由用户使用
ID=5
更新。假设您在删除用户
3
时将该产品作为级联的一部分删除,那么您需要查询由
ID=5
更新的所有产品。你会错过一个产品!或者,您可以保留产品并将
createdBy
设置为
NULL
,这样您就不会错过重要信息。但这当然不是级联删除。您需要问问自己是否真的要删除该用户,以及是否有更好的选择。