这个过程的功能就是把Acess 数据库中4个表的数据传到sql server 数据库对应的4个表中。
AceQuery 连Acess数据表,SqlQuer 连 sql server 数据表,表名和字段名记录在AceList数据中,
此过程放在一个Timer中运行,每执行一次,通过任务管理器都能看到内存涨一点,搞不懂是什么原因,Access 数据库中数据量大时,涨得快些,数据量小时,涨得慢些。
---------------------------------------------------------------------------------------
Procedure TForm1.PushData();
var
  i, j   : integer;
  LastDT : TDateTime; // 记录提交的最后一笔数据的时间,以便把提的数据删除
  LastStr: string;  // 
  UseDT,UseMS  :Cardinal;
begin
  RichMemo.Lines.Add(DateTimetoStr(now)+'  ********* Strart Post Data ********* ');  UseDT  := GetTickCount();
  LastDT := StrToDateTime('1980-8-8'); //为防止误删数据,初始化为一个较小的值  // 提数据
  for i:=0 to 4 do
  begin
    if AceQuery.Active then AceQuery.Close();
    AceQuery.SQL.Clear;
    AceQuery.SQL.Add('select * from '+AceList[i][0]+' order by MCGS_Time asc');    try
      AceQuery.Open;
    except
      DbConnected := false;
      RichMemo.Lines.Add(DateTimetoStr(now)+'   Search Data in Access  failed! ');
      continue;
    end;    if (AceQuery.Bof and AceQuery.Eof) then continue;
    try
      if SqlQuery.Active then SqlQuery.Close;
      SqlQuery.SQL.Clear;
      SqlQuery.SQL.Add('select top 1 * from '+AceList[i][1]);
      SqlQuery.Open;
    except
      DbConnected := false;
      RichMemo.Lines.Add(DateTimetoStr(now)+'   Open sql''s table failed! ');
      continue;
    end;    AceQuery.First;    try
      while(not AceQuery.Eof) do
      begin
        LastDT := AceQuery.FieldValues['MCGS_Time'];
        try
          SqlQuery.Append;
          for j:=2 to High(AceList[i]) do
            SqlQuery.FieldValues[AceList[i][j]] := AceQuery.FieldValues[AceList[i][j]];          SqlQuery.Post;
        except
        on E:Exception do
          // 判断是不是因为关键字重复报错,是的略的,不是就继续抛出异常
          if not GetErrors(E.Message) then Raise Exception.Create('Other Error');
        end;
        AceQuery.Next;
      end;
    except
    on EE:Exception do
    begin
      DbConnected := false;
      RichMemo.Lines.Add(DateTimetoStr(now)+' '+ EE.Message +' '+AceList[i][1]);
      continue;
    end;
    end;    // 删除提过的数据
    LastStr := formatDateTime('yyyy-mm-dd hh::mm::ss',LastDT);
    if AceQuery.Active then AceQuery.Close();
    AceQuery.SQL.Clear;
    AceQuery.SQL.Add('delete from '+AceList[i][0]+' where MCGS_Time <=#'+LastStr+'#');
    AceQuery.ExecSQL;  
  end;
  
  AceQuery.Active := false;
  SqlQuery.Active := false; 
end;

解决方案 »

  1.   

    // 这个和上面是一样的,只是将异常处理删掉,代码简短点,好看些。Procedure TForm1.PushData();
    var
      i, j   : integer;
      LastDT : TDateTime; // 记录提交的最后一笔数据的时间,以便把提的数据删除
      LastStr: string;
      UseDT,UseMS  :Cardinal;
    begin
      RichMemo.Lines.Add(DateTimetoStr(now)+'  Strart Post Data ');  UseDT  := GetTickCount();
      LastDT := StrToDateTime('1980-8-8'); //为防止误删数据,初始化为一个较小的值  // 提数据组
      for i:=0 to 4 do
      begin
        if AceQuery.Active then AceQuery.Close();
        AceQuery.SQL.Clear;
        AceQuery.SQL.Add('select * from '+AceList[i][0]+' order by MCGS_Time asc');    AceQuery.Open;
        if (AceQuery.Bof and AceQuery.Eof) then continue;
        
        if SqlQuery.Active then SqlQuery.Close;
        SqlQuery.SQL.Clear;
        SqlQuery.SQL.Add('select top 1 * from '+AceList[i][1]);
        SqlQuery.Open;    AceQuery.First;
        while(not AceQuery.Eof) do
        begin
          LastDT := AceQuery.FieldValues['MCGS_Time'];
          SqlQuery.Append;
          for j:=2 to High(AceList[i]) do
             SqlQuery.FieldValues[AceList[i][j]] := AceQuery.FieldValues[AceList[i][j]];      SqlQuery.Post;
          AceQuery.Next;
        end;    // 删除提过的数据
        LastStr := formatDateTime('yyyy-mm-dd hh::mm::ss',LastDT);
        if AceQuery.Active then AceQuery.Close();
        AceQuery.SQL.Clear;
        AceQuery.SQL.Add('delete from '+AceList[i][0]+' where MCGS_Time <=#'+LastStr+'#');
        //AceQuery.ExecSQL;  // 此句注释掉,免得又要找测试数据
      end;
    end;
      

  2.   

    代码太长
    自己download一个boundchecker之类的看看吧
      

  3.   

    1.
      for i:=0 to 4 do//Error! 
      begin  end;
    2.
     if (AceQuery.Bof and AceQuery.Eof) then continue;//?????it not simplely3.
    SqlQuery.SQL.Add('select top 1 * from '+AceList[i][1]);//????  Warning你的编程思想不正确,没必要每次只选一条数据,这样查询太频繁,慢!!!!
      

  4.   

    to  Blakhawk(黑鹰船长) ( )
    1.   for i:=0 to 4 do//Error! 
    -----------------------------------------------------------------
    因为要把5个表的数据转过去,所以用了for i:=0 to 4   
    每次打开的数据集都是不一样的。
     
    2. if (AceQuery.Bof and AceQuery.Eof) then continue;//?????it not simplely
    ----------------------------------------------------------------------------
    AceQuery 连接的是Access数据库,要把多个表中转到SqlQuery连接的SQL SERVER数据库中,
    如果AceQuery 打开的一个表的空表,返回就接着打开下一个表3. SqlQuery.SQL.Add('select top 1 * from '+AceList[i][1]);//????  Warning
       你的编程思想不正确,没必要每次只选一条数据,这样查询太频繁,慢!!!!
    -------------------------------------------------------------------------
    SqlQuery 连的Sql Server 数据库,我只是用他写数据,"'select top 1 *" ,只是为了在执行
    SqlQuery.Open,把数据集打开,好象里面写数据。
    --------------------------------------------------------------------------------------
    --------------------------------------------------------------------------------------
    to cdsgajxlp(新手) ( ) 
       数据量比较大时,内存涨的很快的。我试了一下,如果每分钟60条数据的话,二天时间都涨到20M了,如果一个小时十几条数据的话,内存也在涨,只不过涨的很慢,一天大约涨0.1M。
       点一下最小化按钮,内存会降下来,降到1.5M左右,之后又会慢慢涨起来。难到要过一会就发一个最小化的消息吗,这样似乎也太搞笑了。
      

  5.   

    RichMemo.Lines.Add(DateTimetoStr(now)+'  Strart Post Data ');
    这句有问题,richmemo加一行时得申请更多的内存,如果只加而不放的话当然会有上述问题了,建议这样写:
    if richmemo.lines.count > 100 then
      richmemo.lines.clear;
    RichMemo.Lines.Add(DateTimetoStr(now)+'  Strart Post Data ');
      

  6.   

    楼上的,我也想到过这个问题,按你的方法改了,问题依旧。
    另外我也VC做了一个,也是这样,在VC版这个问题也没解决,会不会是ADO的BUG呀。
      

  7.   

    我用的是7.1版本的ADO,下载了一个8.0的,还没装。
      

  8.   

    我现在有一个项目,和你的情况相似,目标也是SQLServer,源包括DB2和SQLServer,也是ADO。导入的时候,内存涨的也比较大,不导入的时候,看来是有回落的,不过好象比较慢。我是一天有几个时间点导入而已,所以还是回落回来。也发现最小化的时候,内存一下子变小的情况,怀疑是ADO方面的内存回收策略导致的。memo在界面写的log,超过几千行就清理一次,影响应该不大。正准备将内存的占用隔段时间写入log,跑上个几天看看,分析一下。再交流。
      

  9.   

    if SqlQuery.Active then SqlQuery.Close;
        SqlQuery.SQL.Clear;
        SqlQuery.SQL.Add('select top 1 * from '+AceList[i][1]);
        SqlQuery.Open;
    我也遇到过这种问题,使用ADO的ADDNEW方法添加数据,内存不停涨。
    后来我这样做,判断ADO中的记录数,如果大于1000,则把ADO关闭一下
    在打开。这样做内存就会先上去然后再下来。但是,也不能根本解决问题。windows窗体最小化能立即释放内存的现象我遇到好多,也无法解释。
    现在测试软件,我查看任务管理器,看内存是否一直增长,系统句柄数是否
    一直增长,比较土。不知各位有什么好方法。
      

  10.   

    这种数据导入/导出的问题,也可以换个角度来考虑。
    SQL SERVER中有DTS导入/导出数据
    也可以使用链接服务器链接到外部数据库中,还有可以编写可以
    定时调用的 作业 ,等等都可以实现数据导入导出的功能。
      

  11.   

    这与代码没关系,SQL数据库就是这样,我的服务器内存是2G,只装了SQL,现在每天的内存占用都是在1.6G以上,嘿嘿,所以为什么服务器对内存要求比对CPU要求高,知道了吧:)
    SQL安装时缺省是动态分配内存,你也可以设置内存配额,比如20M什么的
      

  12.   

    我每次处理玩后都都把记录集关闭了,下次用时再打开,好象不能解决问题。
    DTS我也考虑过,但不大会用,因为我每次只提新数据,不知道怎么设置DTS,使它只提新数据。