如何防止树具有循环引用

时间:2018-10-05 13:17:59

标签: sql-server tree constraints

原始表比较复杂,但是.. 我有一张桌子,里面放着很多树。 即时通讯所看到的是一种非触发式的约束或一个决定快速回滚的触发器。

create table myTreeTable ( 
    id int not null identity(1,1),
    node varchar(80),
    parent varchar(80),
    constraint PK_mytable primary key nonclustered (node)
)

insert into myTreeTable values ('a', null)
insert into myTreeTable values ('b', 'a')
insert into myTreeTable values ('c', 'a')
insert into myTreeTable values ('d', 'a')
insert into myTreeTable values ('e', 'b')
insert into myTreeTable values ('f', 'b')
insert into myTreeTable values ('g', 'd')
insert into myTreeTable values ('h', 'f')
insert into myTreeTable values ('i', 'g')
insert into myTreeTable values ('j', 'g')

insert into myTreeTable values ('aa', null)
insert into myTreeTable values ('bb', 'aa')
insert into myTreeTable values ('cc', 'aa')
insert into myTreeTable values ('dd', 'aa')
insert into myTreeTable values ('ee', 'bb')
insert into myTreeTable values ('ff', 'bb')
insert into myTreeTable values ('gg', 'dd')
insert into myTreeTable values ('hh', 'ff')
insert into myTreeTable values ('ii', 'gg')
insert into myTreeTable values ('jj', 'gg')

我需要防止的是

之类的更新
update myTreeTable set parent='j' where ID=1

或类似

的插入
insert into myTreeTable values ('aaa', 'bbb'),('bbb', 'ccc'),('ccc','aaa')

4 个答案:

答案 0 :(得分:1)

您可以通过下面的查询来检查是否有循环引用:


create trigger check_circular_ref_tgr on myTreeTable for insert, update as
begin

declare @new_node varchar(80), @new_parent varchar(80)

select @new_node=node, @new_parent=parent from inserted

with p(id) as (
select parent from myTreeTable where node = @new_parent
union all 
select parent from myTreeTable inner join p on myTreeTable.node=p.id where parent is not null)

if exists(select id from p where id=@new_node)
  raiseerror(N'circular reference error', 10, 1)

end

答案 1 :(得分:0)

您可以使用Instead of触发器来覆盖更新和插入。看到这样的帖子:How to prevent updates to a table, with an exception for one situation

答案 2 :(得分:0)

您可以添加“后代”表,在该表中,对于每对节点,您记录一个节点是否是另一个节点的后代。它的行数将少于N * N行,因为您不需要完全不相关的节点条目。 (缺少条目表示“不是后代”。)

这将在搜索时提供最快的性能,但是在插入/删除时将导致性能下降,因为您将必须更新“后代”表。

答案 3 :(得分:0)

您可以编写一个函数来检查插入/更改是否会创建循环引用并从CHECK CONSTRAINT调用它。

相关问题