我有一个名为Items的表,其中包含以下三个字段:
NodeId(HierarchyId)
x1 + 1 <= x2
Id NodeId ParentId
2 / NULL
3 /120/1/ 1520
4 /1/ 2
和ParentId
基本上都是重复的,因为它们都指向父对象。将来,NodeId
将会被ParentId
取代。
但是,与此同时,我需要确保它们保持同步,因此我需要写一个约束来确保这一点:
HierarchyId
如何将其写为约束?
更新
我按照建议尝试了Damiens解决方案。它可以对现有数据强制执行多列完整性。但是,NodeId可以在层次结构中从左到右更改。例如,declare @id int = 4
DECLARE @result int = 0, @parentNodeId1 HierarchyId,@parentNodeId2 HierarchyId, @parentId int;
Select @parentNodeId1 = NodeId.GetAncestor(1), @parentId = parentId from Items where id = @id;
Select @parentNodeId2 = NodeId from Items where Id = @parentId;
if @parentNodeId1 = @parentNodeId2
Select @result = 1;
的NodeId可以更改为/1/
。它的父级未更改(父级为/3/
),因此外键实际上尚未生效。这适用于没有孩子的物品。
但是,如果某项包含子项,并且NodeId已更改,则数据库引擎会将其视为违反外键并引发错误。
请参阅此数据库提琴:https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=44637c2bbed80b8db3f305933798cdad
/
答案 0 :(得分:2)
如果我们可以添加另一列,则外键约束可以强制执行此操作:
create table T(
Id int not null,
NodeId hierarchyid,
ParentId int,
_ParentNodeId as NodeId.GetAncestor(1) persisted,
constraint PK_T primary key (Id,NodeId),
constraint FK_T_Parent foreign key (ParentId,_ParentNodeId) references T (Id,NodeId)
)
(我将PK用作FK目标,但是如果Id
是当前PK且您想保留它,则任何唯一约束都将起作用)
我为新列名加上了_
。这是我的惯例,“我出于强制性而在我的中添加此列。我什至不希望其他人看到它”。