首先说下树节点对应的表的基本结构,必需要有的字段(节点编号,父节点编号,节点名称),其他字段根据你开发的需要添加
从添加节点开始,一开始就取出表中最大节点编号,每次添加节点的时候,该节点编号增加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 :=
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 + ;
New(pinteger);
pinteger^ := maxdwbh;
newnode.data := pinteger; if node = nil then
fdwbh :=
else if node.Level = then
fdwbh :=
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 + ;
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', '');
except
on e: Exception do
ShowMessage(e.Message);
end;
end; procedure TForm1.FormCreate(Sender: TObject);
var
sql: string;
begin
try
maxdwbh := ;
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

简单的界面

delphi7 treeview + 数据库 实现动态节点维护的更多相关文章

  1. Redis Cluster 集群节点维护 (三)

    Redis Cluster 集群节点维护: 集群运行很久之后,难免由于硬件故障,网络规划,业务增长,等原因对已有集群进行相应的调整,比如增加redis nodes 节点,减少节点,节点迁移,更换服务器 ...

  2. 修复jquery.treeview的增加子节点的方法的bug

    1.修复理由 在一个android项目中用到了treeview控件(本来自己通过android的原生api实现了一个http://www.cnblogs.com/Mr-Nobody/p/3527688 ...

  3. delphi TreeView修改选中的节点的颜色和背景

      TreeView修改选中的节点的颜色和背景     TCustomDrawTarget = (dtControl, dtItem, dtSubItem);   TCustomDrawStage = ...

  4. Oracle数据库之动态SQL

    Oracle数据库之动态SQL 1. 静态SQLSQL与动态SQL Oracle编译PL/SQL程序块分为两个种:一种为前期联编(early binding),即SQL语句在程序编译期间就已经确定,大 ...

  5. Bootstrap treeview增加或者删除节点

    参考(AddNode: http://blog.csdn.net/qq_25628235/article/details/51719917,deleteNode:http://blog.csdn.ne ...

  6. C#上移,下移TreeView中的树节点顺序

    C#上移,下移TreeView中的树节点顺序 2009-08-12 20:10 1494人阅读 评论(2) 收藏 举报 c#buttonobjectnullstring C#中,通过单击上移,下移按钮 ...

  7. 根据数据库记录动态生成C#类及其公共属性并动态执行的解决方案

    原文:根据数据库记录动态生成C#类及其公共属性并动态执行的解决方案 问题: C#中,想动态产生这么一个类: public class StatisticsData    {        public ...

  8. 重写TreeView,多层级节点下批量显示图片,图片支持缩略图和文件名列表切换,支持调用者动态匹配选中,支持外界拖入图片并添加到对应节点下

    1.先看下整体效果 2.前端代码 <UserControl x:Class="iPIS.UI.Base.Tree.ImageTreeControl" xmlns=" ...

  9. 在DELPHI中用TreeView控件从数据库中动态装载信息

    1.PInfo表结构ID VARCHAR(50)FullName VARCHAR(50)ParentID VARCHAR(50) 2.Unit文件unit Info; interface uses  ...

随机推荐

  1. WebMvcConfig

    package cn.xx.yy; import java.util.ArrayList;import java.util.HashMap;import java.util.List;import j ...

  2. opencv+python 添加文字 cv2.putText

    import cv2 img = cv2.imread('E:\\usb_test\\example\\yolov3\\rknn_emotion\\test_images\\llj5.jpg') fo ...

  3. nginx用指针的值的最后一位来判断过期事件

    nginx中,将地址的最后一位取出来,用Instace变量标识,用来判断是否连接已经被释放成为过期时间 为什么指针地址最后一位一定是0呢? 这里的内存地址,一定是内存分配器分配出来的地址,如new . ...

  4. 如何创建javabeans实例

    如何创建javabeans实例 1.像使用普通java类一样,创建javabean实例 创建一个用户类的javabeans package com.po; /** * * 用户类 * @author ...

  5. C# ClickOnce发布方式

    首先编写ClickOnce更新事件, private void button1_Click(object sender, EventArgs e) { if (ApplicationDeploymen ...

  6. Oracle 后台进程(四)CKPT进程

    一.CKPT简介 检查点是一个数据库事件,它把修改数据从高速缓存写入磁盘,并更新控制文件和数据文件.检查点分为三类:1)局部检查点:单个实例执行数据库所有数据文件的一个检查点操作,属于此实例的全部脏缓 ...

  7. sqlserver中产生随机字符,随机数

    SELECT REPLACE(NEWID(),'-','') select replicate(char(cast(rand()*1000 as int)%26+97) +char(cast(rand ...

  8. 牛客练习赛53 (C 富豪凯匹配串) bitset

    没想到直接拿 bitset 能过 $10^8$~ code: #include <bits/stdc++.h> #define N 1004 #define setIO(s) freope ...

  9. CF 940F - Machine Learning ( 带 修 )

    题目: 链接:https://codeforces.com/problemset/problem/940/F 题意:给你n个数,a[i]有q个操作,操作有两种:操作1.       1 x y 表示询 ...

  10. 2019.6.28 校内测试 T4 【音乐会】达拉崩吧·上

    考试的一道附加题~ 一看题目描述:把区间[l,r]里每个数异或上x,求区间[l,r]里所有数的异或和,这明显的要用数据结构或RMQ吧. 恩,所以正解就是线段树啦,至于树状数组行与否,不知道~ wate ...