★★★追寻修改大型数据库最好办法的往事回顾★★★来者有分!

lgqTiger 2003-12-19 03:53:11
我是一个高考时英语成绩只有25分而与大学无缘的中学生。但是在我92年刚开始投入工作,第一次接触电脑时,一股无以言说的冲动使我深深地爱上了电脑,并与电脑结下了不解之缘,至今我完全以自学方式学习及使用过Borland C++3.x FOX pro 2.5、Visual Basic 5.0、Borland Delphi等。
在今年八月份,我公司主管与我商量,公司现行的ERP for Dos系统的数据库中的商品编号已经位数不足以应付现今的发展需要,要求在保留原数据库的完整性的前提下,将所有数据表中的” Item_Code”即商品编号由原来的8位升格为9位,(条件为”A1234567”升格为A01234567”即在”A”与”1”之间加插入”0”字符)。
我第一时间浏览数据库的大小,当时真使我吃惊,(竟有2G之大的旧版FOX格式数据库)我粗略估计,总数据的笔数绝不少于1000万笔,如果由一个文员用手工修改一定要3个月以上的时间才能完成,而且不能保证其手工差错的可能。这当然是不可取的!那么,该用什么办法才是最快、最好的?就这问题使我陷入了深思之中……。
我第一步尝试,先建一个ODBC连接再用传统的BDE连接到数据库。用循环的方式逐笔数据地处理,大致代码如下:

var
I:Integer;
S1,S2,S3:String;

while not Table1.Eof Do
begin
S1:=Table1.FieldByName(‘Item_Code’).asString;
S2:=Copy(S1,1,1);
S3:=Copy(S1,2,(Lenght(S1)-1));
Table1.Edit;
Table1.FieldByName(‘Item_Code’).asString:=S2+’0’+S3;
Table1.Post;
Table1.Next;
end;

但是效果使我感到很不满,我操作一个大概1万道记录的数据表时花费了30分钟的时间,而且在操作下3万道记录的表时系统就毫不留情地提示出错乃致终止程序。我认定这绝对不是好办法,又让我再次深思……。
第二步:我改用SQL控件,TQuery控件连接数据库,而且按照我的意图用TQuery控件访问数据表中指定的一个字段”ID”其他不访问以提高运行的效率。具体的代码还是与第一次的差不多,这里我不重复。但是问题同样存在,速度一样慢得可怜,我看着它一行一行地跳平均一秒钟才操作一笔数据的蚂蚁速度,让我苦闷难当……。我心想Delphi本是一个对数据有很好的兼容的优秀开发工具,哪怕改用其他的工具写程序可能效果反而会更差。我也考虑过用存储过程,但是它是由数百个旧版的FOX Por 数据表集合在一个目录中而组成的。 存储过程在他身上是没有办法使用的。最后我还是专心改良我的程序,但是该用何法?
第三步:我想我的程序慢而且占用系统大量资源的地方应该在于它逐行的复制字符,又逐行的修改和提交数据这些动作之上。如果我能够取消这些动作,或者说用一句SQL语句来完成,让它所有的动作均隐含在系统内完成,该会多好啊!
一天, 我在书店里看一本《SQL习题与解答》的书时,灵光一动。马上把计算过程的代码改为如下:

procedure TForm1.erpAction(Sender: TObject);
var Sql1,Sql2:String;
begin
Sql1:='Update ';
Sql2:='SET '+
'Item_Code=SUBstr(Item_Code,1,1) + "0" + SUBstr(Item_Code,2, (Len(Item_Code)) ‘
Query1.SQL.Clear;
Query1.SQL.Add(Sql1+List.Text+' '+Sql2);// List.Text是数据表的名称
try
Query1.ExecSQL;
ShowMessage({Query1.Sql.Text}'数据表['+list.Text+ ']已经完成!!');
Finally
Query1.Close;
end;
end;

结果,一个5万道记录的数据表只用了5秒钟就完成了,到了这里我的问题跨前了一大步,但是不遇到了新的麻烦:该ERP数据库里的数据表,有几百个,我总不能够一个一个地写表格名子一份一份地改吧!万一有遗漏怎么办?直到前几天,我看了李维先生的《Delphi 7高效数据程序设计》一书后,我的豁然开朗。
第四步:马上把程序改为:

//设确定按钮的事件代码为:
procedure TForm1.btOKclick(Sender: TObject);
var
nameList:TstringList;
I:Integer;
begin
nameList:=TstringList.Create;
nameList.Clear;
dataBase1.open;
DataBase1.GetTableNames(nameList);
//其中DataBase1连接到数据库,数据集控件帮定到DataBase1上
for I:=0 TO nameList.Count-1 DO
begin
erpAction(nameList.Strings[I]);
end;
end;


//将该事件改为一个可接受一个变量的公用过程
procedure TForm1.erpAction(tableName: String);
var Sql1,Sql2:String;
begin
Sql1:='Update ';
Sql2:='SET '+
'Item_Code=SUBstr(Item_Code,1,1) + "0" + SUBstr(Item_Code,2, (Len(Item_Code)) ‘
Query1.SQL.Clear;
Query1.SQL.Add(Sql1+ tableName +' '+Sql2);// tableName是数据表的名称
try
Query1.ExecSQL;
// ShowMessage({Query1.Sql.Text}'数据表['+ tableName + ']已经完成!!');
Finally
Query1.Close;
end;
end;

最终我只用了二十分钟左右的时间完成了数百个数据表;上1000万笔数据;拥有两个G之大的数据库的升级动作,而且没什么问题出现。我回想起在这十多天来的追寻和学习中,我付出了努力,但是收获的更多…..。

...全文
143 13 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
cow8063 2003-12-19
  • 打赏
  • 举报
回复
好样的
chenkandy 2003-12-19
  • 打赏
  • 举报
回复
能学习就是最好的
delphipan 2003-12-19
  • 打赏
  • 举报
回复
学习搂主的这种执著的精神啊
gencan 2003-12-19
  • 打赏
  • 举报
回复
不会!
午秋 2003-12-19
  • 打赏
  • 举报
回复
学习
Tensionli 2003-12-19
  • 打赏
  • 举报
回复
up
nhdj 2003-12-19
  • 打赏
  • 举报
回复
呵呵,能学习就是最好的
txmjs 2003-12-19
  • 打赏
  • 举报
回复
只能向大家学习了...
Erice 2003-12-19
  • 打赏
  • 举报
回复
可以哟
lgqTiger 2003-12-19
  • 打赏
  • 举报
回复
我最大的遗憾,并不是当时走了弯路而是不知道有CSDN里有那么多热心的朋友可以帮我!
VeryOldMan 2003-12-19
  • 打赏
  • 举报
回复
有此经验,下次你就会直接走第4步,或者第5步。
huayuxing 2003-12-19
  • 打赏
  • 举报
回复
同意楼上的,不知道楼主为什么学了那么多年编程为什么不知道第四点(一开始就知道)
yczyk 2003-12-19
  • 打赏
  • 举报
回复
呵呵,楼主有待学习,我觉得这种问题换成是我应该会直接想到最后一步,而不会走你所说的弯路.不过,楼主的学习总结精神可嘉啊!

5,928

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧