SQLServer数据库之TSql HierarchyID 数据类型用法(sqlserver2008以上有此数据类型)
小标 2018-09-07 来源 : 阅读 1374 评论 0

摘要:本文主要向大家介绍了SQLServer数据库之TSql HierarchyID 数据类型用法(sqlserver2008以上有此数据类型),通过具体的内容向大家展现,希望对大家学习SQLServer数据库有所帮助。

本文主要向大家介绍了SQLServer数据库之TSql HierarchyID 数据类型用法(sqlserver2008以上有此数据类型),通过具体的内容向大家展现,希望对大家学习SQLServer数据库有所帮助。


HierarchyID 数据类型是一种长度可变的系统数据类型。可使用 HierarchyID 表示层次结构中的位置。类型为 HierarchyID 的列不会自动表示树,由应用程序来生成和分配 HierarchyID 值,使行与行之间的所需关系反映在这些值中。
1,字符串表示
必须以“/”开头,以“/”结尾,“/”之间使用数值标识某一个元素,一般是整数或小数,例如“/”,“/1/2/”,“/1/2/3/”,"/1/2/3.1"
2,数据类型的转换


declare @sa Nvarchar(100)
declare @ha HierarchyID
declare @hb HierarchyID

set @sa=‘/1/2/3/‘
set @ha=HierarchyID::Parse(@sa)
set @hb=0x5B5E

select @sa as sa,@ha as ha,@hb.ToString() as hb



3,按深度优先顺序进行比较 
给定两个 hierarchyid 值 a 和 b,a<b 表示在对树进行深度优先遍历时,先找到 a,后找到 b。hierarchyid  数据类型的索引按深度优先顺序排序,在深度优先遍历中相邻的节点的存储位置也相邻。同Level的节点,左边节点小于右边节点,表示左边先被遍历到。


declare @sa Nvarchar(100)
declare @sb Nvarchar(100)
declare @ha HierarchyID
declare @hb HierarchyID

set @sa=‘/1/2/3/‘
set @sb=‘/1/2/‘

set @ha=HierarchyID::Parse(@sa)
set @hb=HierarchyID::Parse(@sb)

if @ha>=@hb
print @sa+‘>=‘+@sb
else 
print @sa+‘<‘+@sb


 4,调用GetLevel()查看HierarchyID的Level,值是从root节点开始的层数。


declare @sa Nvarchar(100)
declare @ha HierarchyID

set @sa=‘/1/2/3/‘
set @ha=HierarchyID::Parse(@sa)

select @sa as sa,@ha as ha,@ha.GetLevel() as Level



5,静态方法GetRoot(),静态方法的调用格式:HierarchyID::GetRoot()

select HierarchyID::GetRoot().ToString() as TootString,HierarchyID::GetRoot() as RootHierarchyID


6,GetDescendant(childleft,childright)用以返回父级的一个子节点,返回的子节点和child是同level的。


declare @sa Nvarchar(100)
declare @sb Nvarchar(100)
declare @sr Nvarchar(100)
declare @ha HierarchyID
declare @hb HierarchyID
declare @hr HierarchyID

set @sa=‘/1/2/3/‘
set @sb=‘/1/2/6/‘
set @sr=‘/1/2/‘
set @ha=HierarchyID::Parse(@sa)
set @hb=HierarchyID::Parse(@sb)
set @hr=HierarchyID::Parse(@sr)

select  @hr.GetDescendant(null,null).ToString(),
        @hr.GetDescendant(@ha,null).ToString(),
        @hr.GetDescendant(@ha,@hb).ToString()



如果LeftChild是‘/1/2/3’,RightChild是‘/1/2/4’,需要在这两个节点之间插入一个新的节点,需要如何处理?表示节点的数字,并不一定必须是正整数,小数也可以,如下,NewChild=’/1/2/3.1/‘;


declare @sa Nvarchar(100)
declare @sb Nvarchar(100)
declare @sr Nvarchar(100)
declare @ha HierarchyID
declare @hb HierarchyID
declare @hr HierarchyID

set @sa=‘/1/2/3/‘
set @sb=‘/1/2/4/‘
set @sr=‘/1/2/‘
set @ha=HierarchyID::Parse(@sa)
set @hb=HierarchyID::Parse(@sb)
set @hr=HierarchyID::Parse(@sr)

select    @hr.GetDescendant(null,null).ToString(),
        @hr.GetDescendant(@ha,null).ToString(),
        @hr.GetDescendant(@ha,@hb).ToString()



7,判断是否是节点的后代,child.IsDescendantOf(parent),如果是,返回1,如果不是,返回0


declare @sa Nvarchar(100)
declare @sb Nvarchar(100)
declare @sr Nvarchar(100)
declare @ha HierarchyID
declare @hb HierarchyID
declare @hr HierarchyID

set @sa=‘/1/2/3/‘
set @sb=‘/1/2/6/‘
set @sr=‘/1/2/‘
set @ha=HierarchyID::Parse(@sa)
set @hb=HierarchyID::Parse(@sb)
set @hr=HierarchyID::Parse(@sr)

select    @ha.IsDescendantOf(@hr),
        @hb.IsDescendantOf(@hr),
        @ha.IsDescendantOf(@hb)



 8,更新HierarchyID的值,必须级联地更新与该节点相关的子节点的值,这是由于HierarchyID类型自身的局限性导致的。
hierarchyid 数据类型具有以下局限性: 

类型为 hierarchyid 的列不会自动表示树。由应用程序来生成和分配 hierarchyid 值,使行与行之间的所需关系反映在这些值中。 某些应用程序可能具有 hierarchyid 类型的列,该列指示在另一个表中定义的层次结构中的位置。
由应用程序来管理生成和分配 hierarchyid 值时的并发情况。不能保证列中的 hierarchyid 值是唯一的,除非应用程序使用唯一键约束或应用程序自身通过自己的逻辑来强制实现唯一性。
由 hierarchyid 值表示的层次结构关系不是像外键关系那样强制实现的。  可能会出现下面这种层次结构关系而且有时这种关系是合理的:A 具有子级 B,然后删除了 A,导致 B 与一条不存在的记录之间存在关系。 如果这种行为不可接受,应用程序在删除父级之前必须先查询其是否有后代

8.1 ,创建数据源


create table dbo.emph2

idpath hierarchyid not null primary key,
id int not null,
parentid as idpath.GetAncestor(1) persisted foreign key references dbo.emph2(idpath),
descr varchar(100)
)



idpath=’/1/2/6/‘的子孙节点如下图

select e.idpath.ToString() as IDPath,e.id,e.parentid.ToString() as ParentIDPath,e.descr
from dbo.emph2 e 
where e.idpath.IsDescendantOf(HierarchyID::Parse(‘/1/2/6/‘))=1


8.2,子节点变更为另一个父节点,例如将idpath=’/1/2/6/‘ 的节点删除,并将其子节点的父节点变更为idpath=’/1/2/7/‘
由于存在外键关系,必须先变更子节点的父节点,然后再删除idpath=’/1/2/6/‘ 的节点。


--delete child notes
--select e.idpath.ToString() as IDPath,e.id,e.parentid.ToString() as ParentIDPath,e.descr
update e set e.idpath=HierarchyID::Parse(‘/1/2/7/‘+cast(e.id as varchar)+‘/‘)
from dbo.emph2 e
where e.idpath.IsDescendantOf(HierarchyID::Parse(‘/1/2/6/‘))=1 and e.idpath!=HierarchyID::Parse(‘/1/2/6/‘)

--delete parent note
delete dbo.emph2 where idpath=HierarchyID::Parse(‘/1/2/6/‘)

--check
select e.idpath.ToString() as IDPath,e.id,e.parentid.ToString() as ParentIDPath,e.descr
from dbo.emph2 e
where e.idpath.IsDescendantOf(HierarchyID::Parse(‘/1/2/7/‘))=1



 8.3,将idpath=’/1/2/6/‘的节点的父节点变更,其子节点仍然是其子节点。
思路是新建一个节点,并将子节点都挂在新节点下。


--create new node
insert into dbo.emph2(idpath,id,descr)
select HierarchyID::Parse(‘/1/3/6/‘),id,descr
from dbo.emph2 e
where e.idpath=HierarchyID::Parse(‘/1/2/6/‘)

--delete child notes
--select e.idpath.ToString() as IDPath,e.id,e.parentid.ToString() as ParentIDPath,e.descr
update e set e.idpath=HierarchyID::Parse(‘/1/3/6/‘+cast(e.id as varchar)+‘/‘)
from dbo.emph2 e
where e.idpath.IsDescendantOf(HierarchyID::Parse(‘/1/2/6/‘))=1 and e.idpath!=HierarchyID::Parse(‘/1/2/6/‘)

--delete parent note
delete dbo.emph2 where idpath=HierarchyID::Parse(‘/1/2/6/‘)

--check
select e.idpath.ToString() as IDPath,e.id,e.parentid.ToString() as ParentIDPath,e.descr
from dbo.emph2 e
where e.idpath.IsDescendantOf(HierarchyID::Parse(‘/1/3/6/‘))=1



 8.4 定向插入新的节点,由于节点之间存在先后顺序,使用GetDescendant(ChildLeft,ChildRight)保证顺序。
在节点 idpath=’/1/2/6/‘ 的子节点 id=15,id=16之间插入一个新的子节点,新的子节点的id=36,descr=‘E1136’,思路是使用GetDescendant(ChildLeft,ChildRight)获取新的IDPath,然后插入到表中。


declare @id int
declare @descr Nvarchar(100)
declare @sa Nvarchar(100)
declare @sb Nvarchar(100)
declare @sr Nvarchar(100)
declare @hnew HierarchyID

set @id=36
set @descr=‘E1136‘
set @sa=‘/1/2/6/15/‘
set @sb=‘/1/2/6/16/‘
set @sr=‘/1/2/6/‘

set @hnew= HierarchyID::Parse(@sr).GetDescendant(HierarchyID::Parse(@sa),HierarchyID::Parse(@sb))

insert into dbo.emph2(idpath,id,descr)
values(@hnew,@id,@descr)



select e.idpath.ToString() as IDPath,e.id,e.parentid.ToString() as ParentIDPath,e.descr
from dbo.emph2 e
where e.idpath.IsDescendantOf(HierarchyID::Parse(‘/1/2/6/‘))=1
order by e.idpath


从排序的结果集中可以看出,id=36的节点,处于id=15和id=16的节点之间,通过GetDescendant(ChildLeft,ChildRight)实现了顺序。
9, HierarchyID类型的数据,很容易实现广度优先遍历和深度优先遍历
9.1,广度优先遍历是指查询层次结构中相同级别的节点

select idpath.ToString() as IDPath,id,parentid.ToString() as ParentIDPath,descr 
from dbo.emph2 where idpath.GetLevel()=2


9.2,深度优先遍历是指遍历一个节点的所有子节点

select idpath.ToString() as IDPath,id,parentid.ToString() as ParentIDPath,descr 
from dbo.emph2 
where idpath.IsDescendantOf(HierarchyID::Parse(‘/1/2/6/‘))=1

以上就介绍了SQL Server的相关知识,希望对SQL Server有兴趣的朋友有所帮助。了解更多内容,请关注职坐标数据库SQL Server频道!

本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程