求教!手动删除目录树节点及其自节点,删除数据库中的内容!高手指点!最好有原代码!(75分)

  • 主题发起人 主题发起人 zhezhe
  • 开始时间 开始时间
Z

zhezhe

Unregistered / Unconfirmed
GUEST, unregistred user!
数据库中存放各节点信息,节点通过自身的ID号唯一确定身份!我在删除带有子节点的
节点时,没能删除其子节点!我不想用触发器!请问手写代码怎么办?sq2000![8D][8D][8D]
代码:
[8D]
type //各字段包含的信息!
PNode=^TNode;
TNode=record
dirId :integer;
dirName :string[50];
dirParendId :integer;//形成树结构的位置
dirNextNode :PNode;
end;
 
1、建议你的dirId采用不等长字符编码,这样就简单多了。
如父节点的dirid为'012',其三个子节点的dirid就可以是
'01201','01202','01203',这样删除该节点的子节点只要用
delete from tablename where dirid like '012%'就可以了。
2、既然都这样了,而且你又不想改数据库结构,试试这样:
写一个递归过程来找到所有子节点的dirId,最后再删除数据库
的记录,但是可能要给TNode添加一个域用来指向当前节点的第
一个子结点。
呵呵,我只会这么多了。
 
to Rainyday
很感谢你的建议,但是如果数据结构改变为你所说的模式,在添加新的节点时的节点ID就不好处理,
因为一个节点可能有很多子节点,如何判断新加入的节点的ID号应该是0120*?谢谢!
 
1、定义data的数据类型在数据类型中加入dirid字段.
加入一个过程,检索节电的所有子节点,确定你的dirid.
方法二
从数据库中检索需要的dirid

但是,在多用户的情况下,很难保证treeview与数据库同步
 
看看我是怎么做的
http://delphibbs.com/delphibbs/dispq.asp?lid=680438
有源程序。
 
你可以分两步,一删除节点,二删除数据
这是我的表结构,与你的不同,不过可以参考一下
create table pjtype
(
class int, //树的层次
hipjcod int, //上一个节点id
pjtype char(100), //该节点在treeview中显示的名称
cnt int, //该节点上所拥有对象数量
typecod int primary key//该节点id
)
create unique index pjtype_idx on pjtype(class,hipjcod,pjtype)

{*********************
删除配件类型(数据库中记录)
*********************}
procedure del_pjtype(in_int:integer);
//删除当前项下所有类型
var
query:tquery;
procedure del_pjtypechilditem(parent_int:integer);
//递归调用删除子项
var
query:tquery;
begin
query:=tquery.Create(application);
query.SQL.Clear;
try
with query do
begin
databaseName:='auto';
sql.add('select pjtype,typecod,cnt from pjtype');
sql.add('where hipjtype=:H_hipjtype');
unprepare;
prepare;
ParamByName('H_hipjtype').asinteger:=parent_int;
open;
while not eof do
begin
if (fieldbyname('cnt').asinteger<>0) then
raise Exception.Create(fields[0].asstring+'项下有汽配零件,删除失败!');
del_pjtypechilditem(fields[1].asinteger);
next;
end;
sql.clear;
sql.add('delete from pjtype where typecod=:H_typecod ');
unprepare;
prepare;
ParamByName('H_typecod').asinteger:=parent_int;
ExecSQL;
end;
finally
query.free;
end;
end;
begin
query:=tquery.Create(application);
query.SQL.Clear;
try
with query do
begin
databaseName:='auto';
sql.add('select pjtype,cnt from pjtype ');
sql.add('where typecod=:H_typecod');
unprepare;
prepare;
ParamByName('H_typecod').asinteger:=in_int;
open;
if (fields[1].AsInteger>0) then
raise Exception.Create(fields[0].asstring+'项下有汽配零件,删除失败!');
del_pjtypechilditem(in_int);
sql.clear;
sql.add('delete from pjtype where typecod=:H_typecod ');
unprepare;
prepare;
ParamByName('H_typecod').asinteger:=in_int;
ExecSQL;
end;
finally
query.free;
end;
end;

以下代码调用上面的过程
try
beginwork;
del_pjtype(ppjdesc(tv_pjtype.selected.data)^.typecod);
tv_pjtype.selected.Delete;
if tv_pjtype.Items.Count=0 then
begin
b_newsub.Enabled:=false;
b_del.Enabled:=false;
end;
Commit;
except
rollback;
raise;
end
 
还有一个地方我忘了,tv_pjtype.selected.delete 应该放在commit之后
 
删除接点可用delete,再根据id从库中删除相关记录
 
to tfnmao:
感谢你的帖子,我还要好好看看才能明白!很可惜我们的数据结构不同,否则我就可以
在程序里调试了!:)不过再次感谢!分过一久再分吧 !

to 魔鬼大师:
我们应该是“老相识”了,你能不能给个详细的方法!泛泛的不是高手呀!要是嫌分少
我可以加!只要你给我方法!我的数据结构已经给你啦!:)
 
既然你不愿意去下载我以前放的源代码,只有我自己找给你了。
看看是否用的著。
=========================================================
procedure TForm1.ToolButton17Click(Sender: TObject);
var
Node,CatNode,ParentNode:TTreeNode;
I:Integer;
begin
if ActiveControl=RichEdit1 then
RichEdit1.ClearSelection
else if ActiveControl=TreeView1 then
begin
Node:=TreeView1.Selected;
ParentNode:=Node.Parent;
if Node.Level=2 then
Table1.Delete
else
begin
if Node.HasChildren then
begin
if MessageDlg('&amp;Eacute;&amp;frac34;&amp;sup3;&amp;yacute;&amp;Otilde;&amp;acirc;&amp;cedil;&amp;ouml;&amp;Ouml;÷&amp;Igrave;&amp;acirc;&amp;Iuml;&amp;Acirc;&amp;Euml;ù&amp;micro;&amp;Auml;×&amp;Ecirc;&amp;Aacute;&amp;Iuml;&amp;Acirc;&amp;eth;?',mtConfirmation,[mbYes, mbNo],0)=idNo then
Exit;
Table1.DisableControls;
try
for I:=0 to Node.Count-1 do
begin
if Table1.Locate('Subject', Node.Item.Text,[]) then
Table1.Delete;
end;
finally
Table1.EnableControls;
end;
end;
Table2.Locate('Level',Node.Text,[]);
Table2.Delete;
end;
TreeView1.Items.Delete(Node);
ParentNode.Selected:=True;
end
else if ActiveControl = ListView2 then
begin
I := 0;
while I < ListView2.Items.Count do
begin
if Listview2.Items.Selected then
begin
if Table1.Locate('Subject',ListView2.Items.Caption,[]) then
Table1.Delete;
Treeview1.Items.Delete(Treeview1.Selected.Item);
Listview1.Items.Delete;
end
else
Inc(I);
end;
end
else if ActiveControl = ListView1 then
begin
CatNode := TreeView1.Selected.Item[Listview1.Selected.Index];
if CatNode.HasChildren then
begin
if MessageDlg( '&amp;Eacute;&amp;frac34;&amp;sup3;&amp;yacute;&amp;Otilde;&amp;acirc;&amp;cedil;&amp;ouml;&amp;Ouml;÷&amp;Igrave;&amp;acirc;&amp;Agrave;&amp;iuml;&amp;micro;&amp;Auml;&amp;Egrave;&amp;laquo;&amp;sup2;&amp;iquest;×&amp;Ecirc;&amp;Aacute;&amp;Iuml;&amp;Acirc;&amp;eth;?',mtConfirmation,[mbYes,mbNo],0)=idNo then
Exit;
Table1.DisableControls;
try { Move table cursor to selected subject }
for I:=0 to CatNode.Count-1 do
begin
if Table1.Locate('Subject', CatNode.Item.Text,[]) then
Table1.Delete;
end;
finally
Table1.EnableControls;
end;
end;
Table2.Locate('Level',CatNode.Text,[]);
Table2.Delete;
ListView1.Selected.Delete;
TreeView1.Items.Delete(CatNode);
end;
end;
 
还不是很清楚你遇到的具体情况,可否再详细说说?
1、如果你是在TreeView里用节点,同时信息存储在数据库中的话,删除节点前可
以使用TreeView提供的方法去遍历每个子结点,遍历的同时即可获得该节点对应的
dirid(可存储在TTreeNode的Data属性中),然后根据该DirId删除数据库的该条记
录,这样,在遍历完所有子结点后,对应的数据库表中记录也删除完了,最后删除
该节点及节点本身对应的记录。这个是比较简单的,即使要支持拖放操作也是较容易
处理的。
2、你所说的节点不是针对TreeView而言,那么在设计数据结构的时候就要仔细考虑
了。因为此时子节点遍历的方法需要你自己做(不象TreeView有相应的方法)。
我以前做过一些均是用不等长编码的方法做的,前提是对每一级节点的数量大体上有
个数,如事先估计第三级子节点一般最多约400个,则可为该级留三位字符长度的编码。
比如从001到999,用户在大量增删之后如果编码超出999,则从头再循环使用;但是要
涉及到数据库查询,据我的经验,速度不是问题。我不太理解你问的“新增节点如何确定
编码......”是什么意思,我做的时候,在新增节点的时候,都有用户界面保证,可以
知道在哪个父节点下面添加的,父节点的编码自然就知道了——如果用TreeView就更不
是什么问题了。我在不使用TreeView的时候,用的是ComboBox让用户在下拉列表中选择
父节点,同时允许双击弹出窗口在更易于可视的区域中选择。如果不选择父节点,则不
允许添加新节点。总之是通过用户界面控制的。







 
后退
顶部