举一个非常简单的例子:比如有一个表:
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上作任何维护操作,最后统一提交给数据库;

解决方案 »

  1.   

    http://www.delphibbs.com/delphibbs/dispq.asp?lid=3277199
      

  2.   

    不知道你用的什么数据库,你考虑过用临时表没有?
           select 
             商品编号,
             商品总数量,
             trunc(商品总数量/包装数量) as  商品整箱数,
             商品总数量-trunc(商品总数量/包装数量) as 商品零数,
             商品总数量,
             包装数量 
           INTO #MYTEMP
    from 商品信息
    select * from #MYTEMP
      

  3.   

    楼上的朋友,我一般用oracle 数据库,您提供的临时表方法,我不太熟练。
    能否再说的具体点,
    但是我有两个疑问:
    1、临时表的数据是不需要保存的;
    2、您通过select * from #MYTEMP 来实现维护数据,那么通过AdoQuery1.UpdateBatch是更改了
    ##MYTEMP,对于原表“商品信息”它是如何处理呢?