国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發 > 綜合 > 正文

樹形數據的處理

2024-07-21 02:08:42
字體:
來源:轉載
供稿:網友
,歡迎訪問網頁設計愛好者web開發。
描述:討論如何處理樹形數據,排序,新增,修改,復制,刪除,數據完整性檢查,匯總統計

表結構描述及數據環境:

         表名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 [email protected]
 while @@rowcount>0
  select @re=right(@idheader+cast(@pid as varchar),@idlen)+','[email protected]
   ,@pid=pid from tb where [email protected]
 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 [email protected]
 while @@rowcount>0
 begin
  if @[email protected]
  begin
   set @re=1
   goto lberr
  end
  select @pid=pid from tb where [email protected]
 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 [email protected]_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 @[email protected]@identity
 exec p_copy @oid,@nid,@new_id
 delete from #temp where [email protected]
end
go

--4.批量復制的存儲過程--復制指定結點及其下面的所有子結點,并生成新結點
create proc p_copystr
@s_id varchar(8000) --要復制項的列表,用逗號分隔
as
declare @nid int,@oid int,@name varchar(20)
set @s_id=','[email protected]_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 @[email protected]@identity
 exec p_copy @oid,@nid,@nid
 delete from #temp where [email protected]
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 [email protected]
 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 [email protected]
 while @pid<>0
 begin
  insert into @re values(@pid)
  select @pid=pid from tb where [email protected]
 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 [email protected])
   goto lberr
  else
   delete from tb where [email protected]
 
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 @[email protected]+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 [email protected]

 

         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 [email protected]) 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

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 名山县| 哈密市| 水富县| 措美县| 山东| 靖安县| 兴海县| 合作市| 建宁县| 习水县| 斗六市| 临漳县| 贵州省| 阳朔县| 弥勒县| 上栗县| 五家渠市| 道真| 武城县| 金溪县| 合川市| 扎赉特旗| 和平县| 广平县| 屯留县| 满洲里市| 宣恩县| 拉孜县| 中方县| 恩施市| 依兰县| 武川县| 西华县| 金阳县| 祥云县| 莆田市| 罗平县| 盐津县| 陆河县| 禄丰县| 哈密市|