Eof没有触发

时间:2016-02-05 21:26:21

标签: sql-server delphi delphi-xe2

我有一个函数,我从DB获取数据,我的测试数据集返回6500行(我从SQLText变量中提取格式化的SQL语句并将其作为测试运行),但是当我运行以下代码时Eof永远不会触发,我已经看到导入了超过10万行。

ADOQuery := TADOQuery.Create(nil);
ADOQuery.ConnectionString := CONNECT_STRING;

// Build SQL Query 
SQLText :=   Format( 'Select  Temp.Serial, Temp.QCSample , Temp.Scrap , Temp.StationID , Temp.Defect , Temp.AddData , Temp2.Serial as Parent_Serial ' +
      'from TAB_ELEMENT as Temp ' + 

      'left join TAB_ELEMENT as Temp2 on  Temp.Parent_Id = Temp2.Element_Id ' + 
      'where Temp.Batch_ID = %d    and Temp.StationID = 0 ',[iSearchID]);

ADOQuery.SQL.Clear;   // Clear query of garbage values
ADOQuery.SQL.Text := SQLText; // Add query text to query module
ADOQuery.Open; 

// Handle Results
iIndexPos := 0; 
tDataImport.BeginUpdate;  

while not ADOQuery.Eof do
begin
    tDataImport.Items[iIndexPos].Serial := ADOQuery.FieldByName('Serial').AsString;
    tDataImport.Items[iIndexPos].QCStatus := ADOQuery.FieldByName('QCSample').AsBoolean;
    tDataImport.Items[iIndexPos].Scrap := ADOQuery.FieldByName('Scrap').AsInteger;
    tDataImport.Items[iIndexPos].StationID := ADOQuery.FieldByName('StationID').AsInteger;
    tDataImport.Items[iIndexPos].Defect := ADOQuery.FieldByName('Defect').AsBoolean;
    tDataImport.Items[iIndexPos].AddData := ADOQuery.FieldByName('AddData').AsString;
    tDataImport.Items[iIndexPos].ParentSerial := ADOQuery.FieldByName('Parent_Serial').AsString;

    inc(iIndexPos);
end;

因此,在夏季使用这些参数运行此查询时,我希望有6500行,当我运行它时,即使在处理了100k +行之后它也永远不会结束。

1 个答案:

答案 0 :(得分:8)

Open()将光标放在第一条记录上并相应地设置Eof。您没有调用Next()将光标前进到下一条记录并更新Eof,因此您一遍又一遍地处理相同的记录:

ADOQuery.Open; 
while not ADOQuery.Eof do
begin
  //...
  ADOQuery.Next; // <-- add this!
end;

另外,您应该使用参数化查询而不是格式化的SQL查询字符串。它在DB上更安全,更快速,更高效:

ADOQuery := TADOQuery.Create(nil);
ADOQuery.ConnectionString := CONNECT_STRING;

ADOQuery.SQL.Text := 'Select  Temp.Serial, Temp.QCSample , Temp.Scrap , Temp.StationID , Temp.Defect , Temp.AddData , Temp2.Serial as Parent_Serial ' +
  'from TAB_ELEMENT as Temp ' + 
  'left join TAB_ELEMENT as Temp2 on  Temp.Parent_Id = Temp2.Element_Id ' + 
  'where Temp.Batch_ID = :iSearchID and Temp.StationID = 0 ';

with ADOQuery.Parameters.ParamByName('iSearchID') do
begin
  DataType := ftInteger;
  Value := iSearchID;
end;

ADOQuery.Open; 
try
  iIndexPos := 0; 
  tDataImport.BeginUpdate;  
  try
    while not ADOQuery.Eof do
    begin
      tDataImport.Items[iIndexPos].Serial := ADOQuery.FieldByName('Serial').AsString;
      tDataImport.Items[iIndexPos].QCStatus := ADOQuery.FieldByName('QCSample').AsBoolean;
      tDataImport.Items[iIndexPos].Scrap := ADOQuery.FieldByName('Scrap').AsInteger;
      tDataImport.Items[iIndexPos].StationID := ADOQuery.FieldByName('StationID').AsInteger;
      tDataImport.Items[iIndexPos].Defect := ADOQuery.FieldByName('Defect').AsBoolean;
      tDataImport.Items[iIndexPos].AddData := ADOQuery.FieldByName('AddData').AsString;
      tDataImport.Items[iIndexPos].ParentSerial := ADOQuery.FieldByName('Parent_Serial').AsString;
      inc(iIndexPos);
      ADOQuery.Next; 
    finally
      tDataImport.EndUpdate;  
    end;
  end;
finally
  ADOQuery.Close; 
end;