分享
 
 
 

树形数据的处理

王朝other·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

描述:讨论如何处理树形数据,排序,新增,修改,复制,删除,数据完整性检查,汇总统计

表结构描述及数据环境:

表名tb,如果修改表名,则相应修改所有数据处理中涉及到的表名tb

id为编号(标识字段+主键),pid为上级编号,name为名称,后面可以自行增加其他字段.

凡是未特殊标注的地方,对自行增加的字段不影响处理结果/*--数据测试环境

表名tb,如果修改表名,则相应修改所有数据处理中涉及到的表名tb

id为编号(标识字段+主键)

pid为上级编号

name为名称,后面可以自行增加其他字段.

凡是未特殊标注的地方,对自行增加的字段不影响处理结果

--表环境

create table tb(id int identity(1,1) not null constraint PK_tb primary key clustered

,pid int,name varchar(20))

insert into 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

--6.得到指定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

--7.得到指定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

--8.删除指定结点

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

--9.得到编码累计及编码级别表,这个是针对全表的,主要是应该于全表处理:

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

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有