/*--表结构描述及数据环境:
表名tb,如果修改表名,则相应修改所有数据处理中涉及到的表名tb
id为编号(标识字段+主键),pid为上级编号,name为名称,后面可以自行增加其他字段.
凡是未特殊标注的地方,对自行增加的字段不影响处理结果
--邹建2003.12(引用请保留此信息)--*/
--测试数据
create table tb(
id int identity(1,1) not null constraint PK_tb primary key clustered,
pid int,name varchar(20))
insert tb select 0,'中国'
union all select 0,'美国'
union all select 0,'加拿大'
union all select 1,'北京'
union all select 1,'上海'
union all select 1,'江苏'
union all select 6,'苏州'
union all select 7,'常熟'
union all select 6,'南京'
union all select 6,'无锡'
union all select 2,'纽约'
union all select 2,'旧金山'
go
--1.自定义函数--获取编码累计
create function f_getmergid(@id int)
returns varchar(8000)
as
begin
declare @re varchar(8000),@pid int
--为了数字排序正常,需要统一编码宽度
declare @idlen int,@idheader varchar(20)
select @idlen=max(len(id))
,@idheader=space(@idlen)
from tb
--得到编码累计
set @re=right(@idheader+cast(@id as varchar),@idlen)
select @pid=pid from tb where id=@id
while @@rowcount>0
select @re=right(@idheader+cast(@pid as varchar),@idlen)+','+@re
,@pid=pid from tb where id=@pid
return(@re)
end
go
--2.自定义函数--检测某个编码出发,是否被循环引用
create function f_chkid(@id int)
returns bit --循环,返回1,否则返回0
as
begin
declare @re bit,@pid int
set @re=0
--检测
select @pid=pid from tb where id=@id
while @@rowcount>0
begin
if @pid=@id
begin
set @re=1
goto lbErr
end
select @pid=pid from tb where id=@pid
end
lbErr:
return(@re)
end
go
/*--数据复制
如果表中包含自定义字段,需要修改存储过程
存在嵌套不超过32层的问题.
--*/
--3.复制指定结点下的子结点到另一个结点下
create proc p_copy
@s_id int, --复制该项下的所有子项
@d_id int, --复制到此项下
@new_id int --新增加项的开始编号
as
declare @nid int,@oid int,@name varchar(20)
select id,name into #temp from tb where pid=@s_id and id<@new_id
while exists(select 1 from #temp)
begin
select @oid=id,@name=name from #temp
insert into tb values(@d_id,@name)
set @nid=@@identity
exec p_copy @oid,@nid,@new_id
delete from #temp where id=@oid
end
go
--4.批量复制的存储过程--复制指定结点及其下面的所有子结点,并生成新结点
create proc p_copystr
@s_id varchar(8000) --要复制项的列表,用逗号分隔
as
declare @nid int,@oid int,@name varchar(20)
set @s_id=','+@s_id+','
select id,name into #temp from tb
where charindex(','+cast(id as varchar)+',', @s_id)>0
while exists(select 1 from #temp)
begin
select @oid=id,@name=name from #temp
insert into tb values(@oid,@name)
set @nid=@@identity
exec p_copy @oid,@nid,@nid
delete from #temp where id=@oid
end
go
--5.得到指定id的子id列表
create function f_getchildid(@id int)
returns @re table(id int)
as
begin
insert into @re select id from tb where pid=@id
while @@rowcount>0
insert into @re select a.id
from tb a inner join @re b on a.pid=b.id
where a.id not in(select id from @re)
return
end
go
--6.得到指定id的父id列表
create function f_getparentid(@id int)
returns @re table(id int)
as
begin
declare @pid int
select @pid=pid from tb where id=@id
while @pid<>0
begin
insert into @re values(@pid)
select @pid=pid from tb where id=@pid
end
return
end
go
--7.删除指定结点
create proc p_delete
@id int, --要删除的id
@deletechild bit=0 --是否删除子 1.删除子,0.如果@id有子,则删除失败.
as
if @deletechild=1
delete from tb where dbo.f_getmergid(id) like dbo.f_getmergid(@id)+'%'
else
if exists(select 1 from tb where pid=@id)
goto lbErr
else
delete from tb where id=@id
return
lbErr:
RAISERROR ('该结点下有子结点,不能删除', 16, 1)
go
--8.得到编码累计及编码级别表,这个是针对全表的,主要是应该于全表处理:
create function f_getbmmerg()
returns @re table(id int,idmerg varchar(8000),level int)
as
begin
declare @idlen int,@idheader varchar(20), @level int
select @idlen=max(len(id)),@idheader=space(@idlen) from tb
set @level=1
insert into @re select id,right(@idheader+cast(id as varchar),@idlen),@level
from tb where pid=0
while @@rowcount>0
begin
set @level=@level+1
insert into @re select b.id,a.idmerg+','+right(@idheader+cast(b.id as varchar),@idlen),@level
from @re a inner join tb b on a.id=b.pid
where a.level=@level-1
end
return
end
go
--应用:
/*--数据显示排序--*/
--分级显示--横向,先一级,后二级...
select * from tb order by pid
--分级显示--纵向
select * from tb order by dbo.f_getmergid(id)
go
/*--数据统计--*/
--分级统计,每个地区下的明细地区数
select *,
明细地区数=(select count(*) from tb where dbo.f_getmergid(id) like dbo.f_getmergid(a.id)+',%')
from tb a order by dbo.f_getmergid(id)
go
/*--数据新增,修改
数据新增,修改(包括修改所属的类别)没有什么技巧
,只需要检查所属的上级是否存在就行了.这个可以简单的用下面的语句来解决:
if exists(select 1 from tb where id=@id) print '存在' else print '不存在'
--*/
--删除'美国'的数据
--exec p_delete 2 --不包含子,因为有美国下有子,所以删除会出错
exec p_delete 2,1 --包含子,将删除美国及所有数据
go
原文参见我在CSDN上发表的贴子
http://expert.csdn.net/Expert/topic/2285/2285830.xml?temp=.1212885
分享到:
相关推荐
sql树形数据处理示例(Jet wang 最新整理).
数据库树形数据处理方案.pdf
典型的sql数据库树形关系,可以根据父找所有的子,也可以指定子找所有的父
#资源达人分享计划#
数据结构为数组中包含对象–树形结构,用Vue组件的写法实现以下的效果: 树形列表,缩进显示层级,第5级数据加底色,数据样式显色,点击展开折叠数据。本文为用Vue实现方式,另有一篇为用knockout.js的实现方法。 ...
otreetable.js 原生JS树形表格,调用非常简单(只需一句代码即可调用),获取HTML中输出的表格数据重构表格,以树形方式显示,可展开/收缩,不破坏表格原有数据格式及内容,支持无限级,兼容所有浏览器。当前版本...
自己写的一个 用java代码复制树形结构数据的方法 很实用 希望对有需求的朋友给予帮助
本书全面系统地介绍了SQL Server开发和管理的应用技术,涉及安装和配置SQL Server、日期处理、字符处理、排序规则、编号处理、数据统计与汇总、分页处理、树形数据处理、数据导入与导出、作业、数据备份与还原、用户...
FlexViewer 树形结构带checkbox,勾选checkbox节点调用地图加载点标注
树图主要用来可视化树形数据结构,是一种特殊的层次类型。 实现方法,将series->type设置为tree。 Echarts的树形图表,可以是正交的,也可以是径向的。 正交树: 径向树: 实现方法,修改:series->layout...
树形菜单是很常用的效果,常用在管理软件当中,但是一套树形菜单已经不能满足需求,所以如果能有一套比较全面的树形菜单JS特效代码,将会非常方便。
主要介绍了vue-cli + element-ui 树形表格(多级表格折腾小计),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
树形表格表单验证预览 树形列表生成序号 首先需要生成一个序号用来确定表单验证的目标row,通过广度优先遍历,以1,1.1,1.1.1的规则对树形列表生成确定唯一值的索引,因为列表自身可以做CURD,因此需要每次列表的...
用于js对平级菜单列表,一级二级菜单对应id的数组对象组合成树形结构数据
有静态树形菜单和动态(从数据库获取数据)树形菜单展示两种 数据库连接采用简单的类实现 数据位MySQL(5.0.21),数据库创建脚本为dtree.sql 菜单既有普通的树结构展示,也有方便做权限等功能的带选择框的展示(含带...
highchecktree是一款使用指定源数据生成带复选框的树形结构的jQuery插件。该树形结构插件对于在大数据的处理上性能十分出色。它使用懒加载的形式来提供性能,子节点会在点击时才去加载数据。
第 8 章 树形数据处理 223 8.1 单编号处理法 223 8.1.1 方法概述 223 8.1.2 逐级汇总 225 8.1.3 编码重排 226 8.1.4 调整编码规则 229 8.1.5 调整编码隶属关系 233 8.2 双编号处理法 238 8.2.1 ...
崇德易城市数据