使用SqlServer2008 Hierarchyid字段类型构造树型分类表
2013-03-01 12:25
211 查看
利用数据库表构造无限级分类,通常我们会采用下面这种方式
![](http://images.cnblogs.com/cnblogs_com/janet/WindowsLiveWriter/SqlServer2008Hierarchyid_E1E2/image_thumb_2.png)
这种主子关系结构清晰,但查询时会有一些小问题;查询当前类别的所有子类及子类下的子孙类,会出现递归查询,而实际应用中这种查询是很常见的,比如我们要查询所有技术类文章信息;
解决这类问题在SqlServer2005出现之前通常是采用游标来操作,但熟悉数据库内部机制的人都知道使用游标带来的性能问题和其他问题是比较严重的
到了SqlServer2005下,可以选择用CTE来做递归查询,例如要查询所有技术类文章,就可使用这种方式,向上递归和向下递归基本实现方式是基本一致的
/*查询所有"技术类文章"类别及其子孙类*/ WITH T_Category(id,name,parentid) as ( SELECT CategoryID,CategoryName,ParentId FROM Category WHERE CategoryID=3 UNION ALL SELECT A.CategoryID,A.CategoryName, A.ParentID FROM Category A ,T_Category B where A.ParentId=B.id ) SELECT * FROM T_Category
![](http://images.cnblogs.com/cnblogs_com/janet/WindowsLiveWriter/SqlServer2008Hierarchyid_E1E2/image_thumb_8.png)
这种方式查询比较简练,但由于数据库内部是采用递归查询的方式,其效率依旧不高;
为了能够实现既简练又高效的查询,通常的做法是增加冗余字段,比如增加一个"Path"字段:
![](http://images.cnblogs.com/cnblogs_com/janet/WindowsLiveWriter/SqlServer2008Hierarchyid_E1E2/image_thumb_3.png)
查询时用模糊查询来进行左匹配,如查询所有文章类别时这样写, Select * from SiteCategory where path like ‘文章%'
对Path建索引后,这种查询的效率还是相当高的,因此这种方式也是一种常规的设计方式;
下面介绍另一种设计方式,利用SqlServer2008中的Hierarchyid字段类型来构造这种结构;
创建一客户地区信息表“Customer”,结构如下
![](http://images.cnblogs.com/cnblogs_com/janet/WindowsLiveWriter/SqlServer2008Hierarchyid_E1E2/image_thumb_4.png)
hierarchyid类型为CLR类型,以二进制形式保存数据,插入部分测试数据
insert into CustomerLocation(ID,location) values('/','全世界') insert into CustomerLocation(ID,location) values('/0/','亚洲') insert into CustomerLocation(ID,location) values('/1/','欧洲') insert into CustomerLocation(ID,location) values('/2/','非洲') insert into CustomerLocation(ID,location) values('/3/','南北美洲') insert into CustomerLocation(ID,location) values('/4/','大洋洲') insert into CustomerLocation(ID,location) values('/0/1/','韩国') insert into CustomerLocation(ID,location) values('/0/0/','中国') insert into CustomerLocation(ID,location) values('/0/0/1/','华北大区') insert into CustomerLocation(ID,location) values('/0/0/2/','华南大区') insert into CustomerLocation(ID,location) values('/0/0/3/','西南大区') insert into CustomerLocation(ID,location) values('/0/0/4/','西北大区') insert into CustomerLocation(ID,location) values('/0/0/1/0/','山东省') insert into CustomerLocation(ID,location) values('/0/0/1/1/','河南省') insert into CustomerLocation(ID,location) values('/0/0/1/0/0/','青岛市') insert into CustomerLocation(ID,location) values('/0/0/1/0/1/','济南市') insert into CustomerLocation(ID,location) values('/0/0/1/0/2/','烟台市') insert into CustomerLocation(ID,location) values('/0/0/1/1/0/','郑州市')
查看表中数据
select *,ID.GetLevel() as 层次 from CustomerLocation
![](http://images.cnblogs.com/cnblogs_com/janet/WindowsLiveWriter/SqlServer2008Hierarchyid_E1E2/image_thumb_5.png)
ID.GetLevel() 是Hierarchyid字段类型内置函数,用于获取当前层次级别,另外提供了一系列相关查询函数,可以方便的查询父子关系数据
向上查询“华北大区”的所有父级直到根级
DECLARE @TID hierarchyid SELECT @TID=ID FROM CustomerLocation WHERE location='华北大区'
SELECT *, ID.GetLevel() as 层次,ID.ToString() as 路径 FROM CustomerLocation WHERE @TID.IsDescendantOf(ID)=1
![](http://images.cnblogs.com/cnblogs_com/janet/WindowsLiveWriter/SqlServer2008Hierarchyid_E1E2/image_thumb_6.png)
向下查询“华北大区”的所有子孙级
DECLARE @TID hierarchyid SELECT @TID=ID FROM CustomerLocation WHERE location='华北大区' SELECT *, ID.GetLevel() as 层次,ID.ToString() as 路径 FROM CustomerLocation WHERE ID.IsDescendantOf(@TID)=1
![](http://images.cnblogs.com/cnblogs_com/janet/WindowsLiveWriter/SqlServer2008Hierarchyid_E1E2/image_thumb_7.png)
该类型的一些主要的函数(下面是引用网上的部分内容):
◆GetAncestor :取得某一个级别的祖先
◆GetDescendant :取得某一个级别的子代
◆GetLevel :取得级别
◆GetRoot :取得根
◆IsDescendantOf :判断某个节点是否为某个节点的子代
◆Parse :将字符串转换为hierarchyid。该字符串的格式通常都是/1/这样的
◆Read :Read 从传入的 BinaryReader 读取 SqlHierarchyId 的二进制表示形式,并将 SqlHierarchyId 对象设置为该值。不能使用 Transact-SQL 调用 Read。请改为使用 CAST 或 CONVERT。
◆GetReparentedValue :可以用来移动节点(或者子树)
◆ToString :将hierarchyid转换为字符串,与parse正好相反
◆Write Write 将 SqlHierarchyId 的二进制表示形式写出到传入的 BinaryWriter 中。无法通过使用 Transact-SQL 来调用 Write。请改为使用 CAST 或 CONVERT。
转自:/article/5745619.html
![](http://images.cnblogs.com/cnblogs_com/janet/WindowsLiveWriter/SqlServer2008Hierarchyid_E1E2/image_thumb_2.png)
这种主子关系结构清晰,但查询时会有一些小问题;查询当前类别的所有子类及子类下的子孙类,会出现递归查询,而实际应用中这种查询是很常见的,比如我们要查询所有技术类文章信息;
解决这类问题在SqlServer2005出现之前通常是采用游标来操作,但熟悉数据库内部机制的人都知道使用游标带来的性能问题和其他问题是比较严重的
到了SqlServer2005下,可以选择用CTE来做递归查询,例如要查询所有技术类文章,就可使用这种方式,向上递归和向下递归基本实现方式是基本一致的
/*查询所有"技术类文章"类别及其子孙类*/ WITH T_Category(id,name,parentid) as ( SELECT CategoryID,CategoryName,ParentId FROM Category WHERE CategoryID=3 UNION ALL SELECT A.CategoryID,A.CategoryName, A.ParentID FROM Category A ,T_Category B where A.ParentId=B.id ) SELECT * FROM T_Category
![](http://images.cnblogs.com/cnblogs_com/janet/WindowsLiveWriter/SqlServer2008Hierarchyid_E1E2/image_thumb_8.png)
这种方式查询比较简练,但由于数据库内部是采用递归查询的方式,其效率依旧不高;
为了能够实现既简练又高效的查询,通常的做法是增加冗余字段,比如增加一个"Path"字段:
![](http://images.cnblogs.com/cnblogs_com/janet/WindowsLiveWriter/SqlServer2008Hierarchyid_E1E2/image_thumb_3.png)
查询时用模糊查询来进行左匹配,如查询所有文章类别时这样写, Select * from SiteCategory where path like ‘文章%'
对Path建索引后,这种查询的效率还是相当高的,因此这种方式也是一种常规的设计方式;
下面介绍另一种设计方式,利用SqlServer2008中的Hierarchyid字段类型来构造这种结构;
创建一客户地区信息表“Customer”,结构如下
![](http://images.cnblogs.com/cnblogs_com/janet/WindowsLiveWriter/SqlServer2008Hierarchyid_E1E2/image_thumb_4.png)
hierarchyid类型为CLR类型,以二进制形式保存数据,插入部分测试数据
insert into CustomerLocation(ID,location) values('/','全世界') insert into CustomerLocation(ID,location) values('/0/','亚洲') insert into CustomerLocation(ID,location) values('/1/','欧洲') insert into CustomerLocation(ID,location) values('/2/','非洲') insert into CustomerLocation(ID,location) values('/3/','南北美洲') insert into CustomerLocation(ID,location) values('/4/','大洋洲') insert into CustomerLocation(ID,location) values('/0/1/','韩国') insert into CustomerLocation(ID,location) values('/0/0/','中国') insert into CustomerLocation(ID,location) values('/0/0/1/','华北大区') insert into CustomerLocation(ID,location) values('/0/0/2/','华南大区') insert into CustomerLocation(ID,location) values('/0/0/3/','西南大区') insert into CustomerLocation(ID,location) values('/0/0/4/','西北大区') insert into CustomerLocation(ID,location) values('/0/0/1/0/','山东省') insert into CustomerLocation(ID,location) values('/0/0/1/1/','河南省') insert into CustomerLocation(ID,location) values('/0/0/1/0/0/','青岛市') insert into CustomerLocation(ID,location) values('/0/0/1/0/1/','济南市') insert into CustomerLocation(ID,location) values('/0/0/1/0/2/','烟台市') insert into CustomerLocation(ID,location) values('/0/0/1/1/0/','郑州市')
查看表中数据
select *,ID.GetLevel() as 层次 from CustomerLocation
![](http://images.cnblogs.com/cnblogs_com/janet/WindowsLiveWriter/SqlServer2008Hierarchyid_E1E2/image_thumb_5.png)
ID.GetLevel() 是Hierarchyid字段类型内置函数,用于获取当前层次级别,另外提供了一系列相关查询函数,可以方便的查询父子关系数据
向上查询“华北大区”的所有父级直到根级
DECLARE @TID hierarchyid SELECT @TID=ID FROM CustomerLocation WHERE location='华北大区'
SELECT *, ID.GetLevel() as 层次,ID.ToString() as 路径 FROM CustomerLocation WHERE @TID.IsDescendantOf(ID)=1
![](http://images.cnblogs.com/cnblogs_com/janet/WindowsLiveWriter/SqlServer2008Hierarchyid_E1E2/image_thumb_6.png)
向下查询“华北大区”的所有子孙级
DECLARE @TID hierarchyid SELECT @TID=ID FROM CustomerLocation WHERE location='华北大区' SELECT *, ID.GetLevel() as 层次,ID.ToString() as 路径 FROM CustomerLocation WHERE ID.IsDescendantOf(@TID)=1
![](http://images.cnblogs.com/cnblogs_com/janet/WindowsLiveWriter/SqlServer2008Hierarchyid_E1E2/image_thumb_7.png)
该类型的一些主要的函数(下面是引用网上的部分内容):
◆GetAncestor :取得某一个级别的祖先
◆GetDescendant :取得某一个级别的子代
◆GetLevel :取得级别
◆GetRoot :取得根
◆IsDescendantOf :判断某个节点是否为某个节点的子代
◆Parse :将字符串转换为hierarchyid。该字符串的格式通常都是/1/这样的
◆Read :Read 从传入的 BinaryReader 读取 SqlHierarchyId 的二进制表示形式,并将 SqlHierarchyId 对象设置为该值。不能使用 Transact-SQL 调用 Read。请改为使用 CAST 或 CONVERT。
◆GetReparentedValue :可以用来移动节点(或者子树)
◆ToString :将hierarchyid转换为字符串,与parse正好相反
◆Write Write 将 SqlHierarchyId 的二进制表示形式写出到传入的 BinaryWriter 中。无法通过使用 Transact-SQL 来调用 Write。请改为使用 CAST 或 CONVERT。
转自:/article/5745619.html
相关文章推荐
- sql server 2008新特性之一HierarchyId 使用SQL Server 2008中的hierarchyid类型来设计具有树型层次关系的表
- Java中的引用类型分类以及使用场景
- 分享学习scala时看到scala仅仅使用ifthenelse构造出boolean类型的精妙代码
- 在oracle中字段类型LONG的使用注意事项
- 对updatetext的使用(更新text,ntext类型的字段)
- Oracle中使用SQL语句修改字段类型总结
- 1.4.2 solr字段类型--(1.4.2.4)使用Dates(日期)
- 1.4.2 solr字段类型--(1.4.2.5)使用枚举字段
- 使用GeoTools遇到的两个小问题:nvarchar类型字段无法识别,主键字段无法识别
- 使用GeoTools遇到的两个小问题:nvarchar类型字段无法识别,主键字段无法识别
- Table 组件使用指南:使用CheckBox组件保存和显示Boolean类型字段
- IValueConverter的使用总结(绑定字段时转换类型)
- 使用正确的姿势更新SSIS Data Flow Component以适应字段类型变化
- mysql字段类型MicrosoftAccess、MySQL以及SQLServer所使用的数据类型
- 构造方法、成员方法的分类及使用及基本类的标准写法
- mysql插入int字段可以使用单引号包含?今天改东西无意发现时间字段成int类型了,而且update这个字段用单引号包含,于是在MySQL上测试下能运行,求解
- 在OpenERP报表中使用selection 类型字段
- db2使用sql语句查询表的字段类型
- mysql字段类型为char类型,建立索引但未使用原因
- 在oracle中字段类型LONG的使用注意事项