本人目前正在学习李维的高效数据库程序设计。书中讲到使用dbExpress控件在包含大量数据纪录的数据源中搜索数据,并介绍使用CloneCursor+SQL语句的方法是最快速的,但有可能产生重复数据。书后介绍了使用一个辅助数据集控件一一检查PacketRecords中的数据是否已经存在,如存在则删除。在使用AppendData把数据加入到原先的数据集控件中。但没有具体介绍如何检查PacketRecords中的数据。请教各位如何检查。

解决方案 »

  1.   

    SQL语句中去掉select distinct ...
      

  2.   

    使用CloneCursor+SQL方法如下:
    其中sdsTest, sdsTemp:TSimpleDataSet
    方法使用一个临时的数据集控件aCDS Clone原数据集控件的游标实现搜索时避免数据集控件将数据源中的大量数据下载到客户端。
    程序首先在临时数据集的游标中查找,若在客户端结果数据集中找到想要的数据,则将数据集的当前纪录设置为该纪录。如果搜寻的数据不在客户端数据集中,则使用另一个临时数据集在后端数据源中搜寻。如果搜寻到纪录则将其添加到客户端的数据集中并设置当前纪录为此纪录。
    参考代码如下:
    procedure TForm1.btnSmartLocate2Click(Sender: TObject);
    var
      aCDS : TClientDataSet;
    begin
      aCDS := TClientDataSet.Create(Self);
      try
        aCDS.CloneCursor(dmData.sdsTest, True);
        if aCDS.Locate('ID', edtID.Text, [loCaseInsensitive, loPartialKey]) then
          dmData.sdsTest.MoveBy(aCDS.RecNo - dmData.sdsTest.RecNo)
        else
        begin
          dmData.sdsTemp.Active := False;
          try
            dmData.sdsTemp.DataSet.ParamByName('ID').Value := edtID.Text;
            dmData.sdsTemp.Active := True;
            if(dmData.sdsTemp.RecordCount >0) then
            begin
              dmData.sdsTest.AppendData(dmData.sdsTemp.Data, False);
              dmData.sdsTest.MoveBy(dmData.sdsTest.RecordCount - dmData.sdsTest.RecNo);
            end;
          finally
            dmData.sdsTemp.Active := False;
          end;
        end;
      finally
        aCDS.Free;
      end;
    end;此种方法可以提供最快的搜寻效率,且产生的网络流量也最少。但是当客户使用DBGrid组件向后浏览数据纪录时,有可能再次得到刚才所添加的纪录而造成客户端结果数据集中的纪录重复。
    李维先生在最后提到可以先使用一个临时数据集控件拷贝原来的数据集Data特性值,当原来的数据集访问每一个随后的数据封包时,先在拷贝的数据集中一一检查数据包中的纪录是否已经存在。如果已经存在则将其从数据封包中删除。当数据封包中的数据都检查完毕后,再使用AppendData把数据加入到原先的数据集中。请高手指教如何对数据封包中的数据进行一一检查。即如何获得数据集向后端数据源发出获取下一个数据封包的请求后,数据源所获得的该数据封包中的数据。
      

  3.   

    李维的话也不可全信,如果网络带宽不是很窄的话,我认为还是直接用sql语句比较好,如果数据比较多的话,前台判断有没有重复数据会更费时。
      

  4.   

    将PacketRecords设置得较小时(如设置为10)并不会费时。请指教如何对数据封包中的数据进行一一检查。即如何获得数据集从后端数据源得到的数据封包中的数据。
      

  5.   

    此方法应用于在服务器端拥有非常多的数据时客户端对纪录的查找。
    dbExpress在使用Locate方法查找数据时默认的行为是将服务器端的数据全部下载到客户端后再进行查找。这样会造成网络拥挤。
    sdsTemp为select * from PERFTEST where ID = :IDTClientDataSet下载数据时默认的行为是将服务器端的数据全部下载到客户端。可以通过设置PacketRecords特性控制一次下载到客户端的纪录数。如设置为10,则每次只下载10条纪录,此10条纪录将被封装为一个数据封包由TDataSetProvider提供给TClientDataSet。当用户向后浏览此10条纪录之后的数据时,TClientDataSet会向服务器端的TDataSetProvider发送消息请求下一个数据封包。目前的问题是如何得到该数据封包中包含的这10条纪录。
    请高手指教。