首先說下樹節點對應的表的基本結構,必需要有的字段(節點編號,父節點編號,節點名稱),其他字段根據你開發的需要添加
從添加節點開始,一開始就取出表中最大節點編號,每次添加節點的時候,該節點編號增加1;
添加節點的時候我們有2個步驟,首先是給treeview樹種建立節點;其次是給數據庫中添加相應的節點記錄;
添加節點樹的時候,需要注意的是要把該節點的節點編號加入到該節點的data屬性中.
在數據庫中加入節點記錄的時候,節點編號和父節點編號都不能少,如果是第0層節點,那么該節點的父節點編號是'0'(這種情況你自己定義,我在這里設為'0')
顯示節點我寫了一個通用函數來實現的
刪除節點由於要刪除該節點及其所有后代節點在表中的記錄,這個在sql server中好像沒有什么好的語句,我寫了一個存儲過程來實現的
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ComCtrls, ShellAPI, DB, ADODB; type TForm1 = class(TForm) tv1: TTreeView; btn_addtj: TButton; btn_addzjd: TButton; btn_del: TButton; edt_jdmc: TEdit; Label1: TLabel; btn_xs: TButton; con1: TADOConnection; qry1: TADOQuery; qry2: TADOQuery; procedure btn_addtjClick(Sender: TObject); procedure btn_addzjdClick(Sender: TObject); procedure btn_delClick(Sender: TObject); procedure btn_xsClick(Sender: TObject); procedure FormCreate(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; maxdwbh: integer; procedure addChildNodes(tv: TTreeView; fnode: TTreeNode; qry: TADOQuery); overload; procedure addChildNodes(tv: TTreeView; fnode: TTreeNode; qry: TADOQuery; tab, jdbh, jdmc, fjdbh, nilfjdbh: string); overload; implementation {$R *.dfm} { 功能:在一個treeview中顯示數據庫中父子節點,並且把節點的編號存入自己的data屬性中 參數:tv 展示樹 fnode 表示tv中的節點,第一次調用通常這個節點取nil qry 一個ADOQuery控件,用來做查詢 tab 我們的父子節點存放的數據庫表名稱 jdbh tab中節點編號代表的字段名稱 jdmc tab中節點名稱代表的字段名稱 fjdbh tab中父節點編號代表的字段名稱 nilfjdbh 樹中第0級節點的父節點字段給分配的值 注意:我們的樹在添加(子)節點的時候也要把它的節點的編號存入到該節點的data屬性中 } procedure addChildNodes(tv: TTreeView; fnode: TTreeNode; qry: TADOQuery; tab, jdbh, jdmc, fjdbh, nilfjdbh: string); var sql, fdwbh: string; node, newnode: TTreeNode; pinteger: ^string; begin //判斷表中有沒有節點,如果連第0級節點都不存在,我們也就不需要顯示樹了 sql := 'select * from tab where fjdbh=''' + nilfjdbh + ''''; qry.Close; qry.SQL.Clear; qry.SQL.Add(sql); qry.Open; if not qry.IsEmpty then begin if fnode = nil then fdwbh := nilfjdbh else fdwbh := string(fnode.data^); //取出節點fnode的全部子節點的記錄 sql := 'select ' + jdbh + ',' + jdmc + ',' + fjdbh + ' from ' + tab + ' where ' + fjdbh + '=''' + fdwbh + ''' order by ' + jdbh; qry.Close; qry.SQL.Clear; qry.SQL.Add(sql); qry.Open; //樹中加入子節點 if not qry.IsEmpty then //有子節點 begin //添加一個節點的所有子節點 qry.First; while not qry.Eof do begin newnode := tv.Items.AddChild(fnode, qry.fieldbyname(jdmc).AsString); New(pinteger); pinteger^ := qry.fieldbyname(jdbh).AsString; newnode.Data := pinteger; qry.Next; end; //定位下一個該操作的節點 if fnode = nil then node := tv.Items.GetFirstNode else node := fnode.getFirstChild; //遞歸調用對下一個子節點進行同樣的操作 addChildNodes(tv, node, qry, tab, jdbh, jdmc, fjdbh, nilfjdbh); end else //沒有子節點的情況,取它的下一個兄弟節點遞歸調用 begin node := fnode.GetNext; if node <> nil then addChildNodes(tv, node, qry, tab, jdbh, jdmc, fjdbh, nilfjdbh); end; end; end; procedure addChildNodes(tv: TTreeView; fnode: TTreeNode; qry: TADOQuery); var fdwbh: Integer; sql: string; node, newnode: TTreeNode; Pdata: ^Integer; begin if fnode = nil then fdwbh := 0 else fdwbh := Integer(fnode.data^); //取出節點fnode的全部子節點的記錄 sql := 'select dwbh,dwmc,fdwbh from zzjgbmb where fdwbh=' + inttostr(fdwbh) + ' order by dwbh'; qry.Close; qry.SQL.Clear; qry.SQL.Add(sql); qry.Open; //樹中加入子節點 if not qry.IsEmpty then //有子節點 begin //添加一個節點的所有子節點 qry.First; while not qry.Eof do begin newnode := tv.Items.AddChild(fnode, qry.fieldbyname('dwmc').AsString); New(Pdata); Pdata^ := qry.fieldbyname('dwbh').AsInteger; newnode.Data := Pdata; qry.Next; end; //定位下一個該操作的節點 if fnode = nil then node := tv.Items.GetFirstNode else node := fnode.getFirstChild; //遞歸調用對下一個節點進行同樣的操作 addChildNodes(tv, node, qry); end else //沒有子節點的情況 begin node := fnode.GetNext; if node <> nil then addChildNodes(tv, node, qry); end; end; procedure TForm1.btn_addtjClick(Sender: TObject); var jdmc, sql: string; fdwbh: integer; node, newnode: TTreeNode; pinteger: ^integer; begin try node := tv1.Selected; jdmc := edt_jdmc.text; newnode := tv1.Items.add(node, jdmc); maxdwbh := maxdwbh + 1; New(pinteger); pinteger^ := maxdwbh; newnode.data := pinteger; if node = nil then fdwbh := 0 else if node.Level = 0 then fdwbh := 0 else fdwbh := Integer(node.Parent.data^); sql := 'insert into zzjgbmb(dwbh,fdwbh,dwmc) values(' + inttostr(maxdwbh) + ',' + inttostr(fdwbh) + ',''' + jdmc + ''')'; qry1.Close; qry1.SQL.Clear; qry1.SQL.Add(sql); qry1.ExecSQL; ShowMessage('單位"' + jdmc + '"添加成功!'); except on e: Exception do ShowMessage(e.Message); end; end; procedure TForm1.btn_addzjdClick(Sender: TObject); var jdmc, sql: string; fdwbh: integer; node, newnode: TTreeNode; pinteger: ^integer; begin try jdmc := edt_jdmc.text; node := tv1.Selected; newnode := tv1.Items.AddChild(node, jdmc); maxdwbh := maxdwbh + 1; New(pinteger); pinteger^ := maxdwbh; newnode.Data := pinteger; if node = nil then Exit else fdwbh := Integer(node.data^); sql := 'insert into zzjgbmb(dwbh,fdwbh,dwmc) values(' + inttostr(maxdwbh) + ',' + inttostr(fdwbh) + ',''' + jdmc + ''')'; qry1.Close; qry1.SQL.Clear; qry1.SQL.Add(sql); qry1.ExecSQL; ShowMessage('單位"' + jdmc + '"添加成功!'); except on e: Exception do ShowMessage(e.Message); end; end; procedure TForm1.btn_delClick(Sender: TObject); var node: TTreeNode; dwbh: integer; sql: string; begin try node := tv1.Selected; node.Delete; dwbh := Integer(node.data^); sql := 'exec p_zzjgbmb_delnode ' + inttostr(dwbh); qry1.Close; qry1.SQL.Clear; qry1.SQL.Add(sql); qry1.ExecSQL; except on e: Exception do ShowMessage(e.Message); end; end; procedure TForm1.btn_xsClick(Sender: TObject); begin try tv1.Items.Clear; addChildNodes(tv1, nil, qry1, 'zzjgbmb', 'dwbh', 'dwmc', 'fdwbh', '0'); except on e: Exception do ShowMessage(e.Message); end; end; procedure TForm1.FormCreate(Sender: TObject); var sql: string; begin try maxdwbh := 0; sql := 'select max(dwbh) maxdwbh from zzjgbmb'; qry1.Close; qry1.SQL.Clear; qry1.SQL.Add(sql); qry1.Open; if not qry1.isempty then begin qry1.First; maxdwbh := qry1.fieldbyname('maxdwbh').AsInteger; end; except on e: Exception do showmessage(e.message); end; end; end.
刪除節點及其后代節點的存儲過程
create procedure [dbo].[p_zzjgbmb_delnode](@dwbh int) as begin declare @tmp1 table (dwbh int) declare @tmp2 table (dwbh int) declare @tmp3 table (dwbh int) insert into @tmp1 select dwbh from zzjgbmb where fdwbh=@dwbh insert into @tmp3 select dwbh from @tmp1 while exists(select dwbh from zzjgbmb where fdwbh in (select dwbh from @tmp1)) begin delete @tmp2 insert into @tmp2 select dwbh from zzjgbmb where fdwbh in (select dwbh from @tmp1) delete @tmp1 insert into @tmp1 select dwbh from @tmp2 insert into @tmp3 select dwbh from @tmp1 end delete from zzjgbmb where dwbh in (select dwbh from @tmp3); delete from zzjgbmb where dwbh = @dwbh end
簡單的界面