有一个部门表 xdepartment,表结构如下:
  DEPARTMENTID     NUMBER(38) not null,
  DEPARTMENTNAME   VARCHAR2(1000) not null,
  E_DEPARTMENTNAME VARCHAR2(1000) not null,
  TREEID           VARCHAR2(1000),
  TRAINNINGTAG     VARCHAR2(1),
  REMARK           VARCHAR2(1000),
  E_REMARK         VARCHAR2(1000)
treeid是上下级部门的编号
1  561 test test
2  265 PT准备室铸造科 PT准备室铸造科                    0101011405
3 282 服务支持采购部设备采购科 服务支持采购部设备采购科  0103010605
4 301 水平事业开发部汽车金融业务科 水平事业开发部汽车金融业务科 0101021903
5 441  政策研究科 政策研究科                                0101002705
6  442  乘用车财务部业务管理科 乘用车财务部业务管理科            0104010107
7 221 综合技术科 综合技术科            0101010709
8 321 工厂经费采购科 工厂经费采购科             0101040508
9 421 服务支持采购部设备采购科 服务支持采购部设备采购科 0101040507
11 521 台上试验科 台上试验科                0102010309
12 241 中长期商品企划科 中长期商品企划科                 0105010106
13 263 PT准备室品质保证科 PT准备室品质保证科                0101011403
14 264 PT准备室保全科 PT准备室保全科 0101011404
15 266 PT准备室机加工科 PT准备室机加工科 0101011406
16 302 商口规划部跨车型规划科 商口规划部跨车型规划科 0105010107
17 303 第一开发部排放认证实验科 第一开发部排放认证实验科 0102010107
18 401 采购二科 采购二科                                     0103010207
19 1 东风汽车有限公司 东风汽车有限公司                   01
假如TREEID 0101或0102 ....,他的上级部就是01 ,如果TREEID 为010101或010102,01013.... 它的上级部0101,现在如果把0101改成了0102 就要把010101,010102,010103....改成为010201,010202,010203.....
请问用触发器怎么来实现。

解决方案 »

  1.   

    楼主,列出的数据太乱了,你要以最简单的方法表达的你意思,列的数据最好以A\b\c\1\2\3这样的方式
      

  2.   

    /*引用*/樹行資料處理 
    描述:討論如何處理樹形資料,排序,新增,修改,複製,刪除,資料完整性檢查,匯總統計 
    表結構描述及資料環境: 
    表名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
      

  3.   

    --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
    --示例數據
    create table tb(id int,pid int,name varchar(20))
    insert tb select 1,0,'a'
    union all select 2,1,'b'
    union all select 3,1,'g'
    union all select 4,2,'c'
    union all select 5,2,'d'
    union all select 6,5,'e'
    union all select 7,5,'f'
    go--查詢處理函數
    create function f_cid(
    @name varchar(10)
    )returns @re table(id int,[level] int)
    as
    begin
    declare @l int
    set @l=0
    insert @re select a.id,@l
    from tb a,tb b
    where a.pid=b.id and b.name=@name
    while @@rowcount>0
    begin
    set @l=@l+1
    insert @re select a.id,@l
    from tb a,@re b
    where a.pid=b.id and b.[level]=@l-1
    end
    delete a from @re a
    where exists(
    select 1 from tb where pid=a.id)
    return
    end
    go--調用(查詢所有的子)
    select a.*,層次=b.[level] from tb a,f_cid('b')b where a.id=b.id
    go--刪除測試
    drop table tb
    drop function f_cid/*--結果
    id          pid         name                 層次          
    ----------- ----------- -------------------- ----------- 
    4           2           c                    0
    6           5           e                    1
    7           5           f                    1(所影響的行數為 3 行)
    --*/
    create table new_tree  ( parent varchar(80), child varchar(80),weight int)
    go
    insert new_tree values ( '1','2',3);
    insert new_tree values ( '1','3',4);
    insert new_tree values ( '2','4',3);
    insert new_tree values ( '2','5',5);
    insert new_tree values ( '3','6',7);
    insert new_tree values ( '3','7',3);
    insert new_tree values ( '3','8',2);
    insert new_tree values ( '6','9',1);
    insert new_tree values ( '5','10',4);
    insert new_tree values ( '4','11',3);
    insert new_tree values ( '9','12',7);
    insert new_tree values ( '7',NULL,1);
    insert new_tree values ( '8',NULL,4);
    insert new_tree values ( '10',NULL,3);
    insert new_tree values ( '11',NULL,3);
    insert new_tree values ( '12',NULL,7);廣度優先:
    create proc proc_new_tree (@parent varchar(80),@mode int =0)
    asbegin
      set nocount on
      declare @level int  
      declare @tmp1  table ( parent varchar(80), child varchar(80),level int)
      select @level =1
      insert @tmp1 select parent,child,@level from new_tree where parent = @parent
      while exists(select * from @tmp1 where child is not NULL and level=@level)
      begin
        insert @tmp1 select a.parent,a.child ,@level+1  from new_tree a,@tmp1 b where a.parent = b.child and b.level=@level
        select @level=@level +1
      end
      if @mode =0 select * from @tmp1
      else select * from @tmp1 where child is null
      set nocount off
    end
    go深度優先:
    create proc proc__tree (@parent char(20))
     as
    begin
      set nocount on
      declare @level int ,@i int ,@flag int
      declare @stack table (parent char(20),child char(20),level int,row int , flag int)
      select @level = 1,@i=1,@flag=1
      insert @stack select parent,child, @level,0,1 from   new_tree  where parent = @parent and child is not null
      
      while @level > 0
      begin
        if exists (select * from @stack where level = @level and flag=1)
        begin
           select @parent = min(child) from @stack  where level = @level and flag=1
           update @stack set flag =0 , row=@i where level = @level and child = @parent and  flag =1
           select @i = @i +1
           insert @stack select parent,child, @level + 1,0,1 from   new_tree  where parent = @parent and child is not null
           if @@rowcount > 0
              select @level = @level + 1
        end
        else
        begin
          select @level = @level - 1
        end
      end 
      select row,parent ,child,level from @stack order by row
      set nocount off
    end
    go
    proc__tree '1'---这个会给你启发。。