AdoQuery的 UpdateBatch的问题
青云 2005-11-26 07:37:02 举一个非常简单的例子:
比如有一个表:
create table 商品信息
(
商品编号,
商品总数量,
包装数量
)
其中:
"包装数量" 是指: 一个箱子里所装的商品数量;
数据是:
商品编号 商品总数量 包装数量
001 107 10
002 190 20
这个表非常简单;
我们做个程序对这个表维护,非常简单;
只需要设置:
AdoQuery1.LockType:=ltBatchOptimistic;//批量更新数据模式;
AdoQuery1.Sql.text:='select 商品编号,商品总数量,包装数量 from 商品信息';
AdoQuery1.open;
DataSource1.DataSet:=AdoQuery1;
DbGrid1.DataSource:=DataSource1;
如果需要维护数据,我们可以直接在DbGrid1上进行修改实现;
如果写程序,就5句代码实现所有的维护功能;
//1、添加
AdoQuery1.Append;
//2、修改
AdoQuery1.Edit;
//3、删除
AdoQuery1.delete;
//4、保存
AdoQuery1.UpdateBatch;
//5、取消
AdoQuery1.CancelBatch;
多么简单的程序,不需要专门写'insert into...'这样的语句实现维护;
而且也不需要我们人为判断哪些数据被更新过,AdoQuery1.UpdateBatch时会自动通过
AdoQuery1.UpdateStatus 来识别哪些数据被更改过,系统会生成相应的Sql语句作更新;
但是,大家注意没有“商品总数量 包装数量”显示的信息不够直观;
如果我们把:
商品编号 商品总数量 包装数量
001 107 10
002 190 20
换成这样的显示:
商品编号 商品整箱数 商品零数 商品总数量 包装数量
001 10 7 107 10
002 9 10 190 20
我想客户会看的更明白;
同样客户在进行单据维护的时候,也是直接输入:“商品整箱数” 和“商品零数 ”来实现;
但是这两个字段不存在,是通过我们算出来的,真实的数量信息只有“商品总数量”这个字段;
所以我想这样做程序:
//1、设置;
AdoQuery1.Sql.text:=
'select
商品编号,
商品总数量,
trunc(商品总数量/包装数量) as 商品整箱数,
商品总数量-trunc(商品总数量/包装数量) as 商品零数,
商品总数量,
包装数量 from 商品信息';
AdoQuery1.FieldByName('商品整箱数').ReadOnly:=false; //允许维护;
AdoQuery1.FieldByName('商品零数').ReadOnly:=false; //允许维护;
AdoQuery1.FieldByName('商品总数量').ReadOnly:=true; //不让维护;
//更新总数量
procedure Tform1.AdoQuery1BeforePost(DataSet:TdataSet);
begin
AdoQuery1.FieldByName('商品总数量'):= AdoQuery1.FieldByName('商品整箱数').asInteger*
AdoQuery1.FieldByName('包装数量').asInteger+
AdoQuery1.FieldByName('商品零数').asInteger;
end;
//2、维护
AdoQuery1.Append;
AdoQuery1.Edit;
AdoQuery1.Delete;
3、保存
AdoQuery1.UpdateBatch;
这样的做法非常非常简单,但是如果大家真的按照这种做法作,会发现有问题:
比如:
你在DbGrid上填写了一个“商品整箱数”和“商品零数”,当你在DBGrid上定位到其它记录上再回到着这条记录的时候,你会发现该记录中的"商品整箱数"和"商品零数"全部为空,也就说你刚才写的没有效果;
这种现象说明一个非常重要的一个问题:
AdoQuery只对表里原生字段的维护敏感,对于经过函数变换后生成的字段,它是不能识别的。
为了实现能够在"商品整箱数"和"商品零数"这两个字段上维护的功能。我尝试了很多方法;
最简单的方法就是改变Sql语句的写法:
AdoQuery1.Sql.text:=
'select * from
(select
商品编号,
商品总数量,
trunc(商品总数量/包装数量) as 商品整箱数,
商品总数量-trunc(商品总数量/包装数量) as 商品零数,
商品总数量,
包装数量 from 商品信息)';
这样在"商品整箱数"和"商品零数"上维护了,
但是这样产生了一个致命的问题:AdoQuery1.UpdateBatch; 这个非常生猛的保存函数实效了;
我们更新数据只能自己手工写更新语句“insert into ... ,update .. delete ”,这还不是最麻烦的。
最麻烦的是:我们还要判断哪些数据是被添加的,哪些数据是被修改的。哪些数据是被删除的。哪些数据没有发生变化; 而如果能用 AdoQuery1.UpdateBatch;就什么都不用考虑;
我提出了这个问题,希望大家提出建议;
也许有人会说把
create table 商品信息
(
商品编号,
商品总数量,
包装数量
)
修改成:
create table 商品信息
(
商品编号,
商品整箱数,
商品零数,
包装数量
)
但是我这里是提出一个现象,希望大家能够在不改变表结构的情况下,以最简单的方法解决这个问题;
希望能至少实现以下几点:
1、不需要自己手工写"insert into ..."这样的语句实现更新数据;
2、不需要判断哪些表作了什么样的更改,能够通过系统自动识别;
3、数据批量更新,可以任意在DbGrid上作任何维护操作,最后统一提交给数据库;