Eas*_*ere 13 c# sql sql-server circular-reference
这是一个非常常见的问题,但我还没有找到我正在寻找的确切问题和答案.
我有一个表有一个FK指向它自己的PK的表,以启用任意深层次结构,就像经典的tblEmployee一样,它的列Manager
是带有PK tblEmployee.EmployeeID的FK.
让我们在我的应用程序中说,用户
tblEmployee.Manager
NULL的这两个记录.tblEmployee
.现在该表是循环引用而不是正确的树.
确保在应用程序中无法完成步骤3 的最佳方法是什么?我只需要确保它将拒绝执行最后一次SQL更新,而是显示一些错误消息.
我不是在挑剔它是SQL Server中的数据库约束(必须在2008年或2012年工作),还是在我的C#app的业务逻辑层中使用某种验证例程.
mel*_*okb 17
您可以使用CHECK CONSTRAINT
该验证经理ID不是循环.您不能在检查约束中具有复杂查询,但如果首先将其包装在函数中,则可以:
create function CheckManagerCycle( @managerID int )
returns int
as
begin
declare @cycleExists bit
set @cycleExists = 0
;with cte as (
select E.* from tblEmployee E where ID = @managerID
union all
select E.* from tblEmployee E join cte on cte.ManagerID = E.ID and E.ID <> @managerID
)
select @cycleExists = count(*) from cte E where E.ManagerID = @managerID
return @cycleExists;
end
Run Code Online (Sandbox Code Playgroud)
然后你可以使用这样的约束:
alter table tblEmployee
ADD CONSTRAINT chkManagerRecursive CHECK ( dbo.CheckManagerCycle(ManagerID) = 0 )
Run Code Online (Sandbox Code Playgroud)
这将阻止添加或更新记录以从任何来源创建循环.
编辑:一个重要的注意事项:检查约束在它们引用的列上得到验证.我最初将其编码为检查员工ID的周期,而不是经理ID.但是,这不起作用,因为它仅在更改ID列时触发.此版本确实有效,因为它会在任何时候触发ManagerID
更改.