3

我有一个使用 ADO 连接在 SQL 数据库上执行查询的函数,它只是为数据库条目提供单个结果,该数据库条目只能与一种SELECT查询类型匹配(即从 ID 中获取 x 值45,其中只有一个 ID 45 条目)。

该函数工作正常,直到我遇到一个不返回结果的查询。查询只是挂起,应用程序无法继续。这是一个示例查询字符串:

'SELECT Cost FROM MaterialCost ' +
'WHERE MaterialType = ''' + 'MS' +
''' AND Thickness = ''' + '0.250' + '''';

同样,这个确切的字符串可以正常工作,直到我可能查询我之前知道的不存在的东西,它应该返回 null 或空字符串。这是功能:

function SelectOneQuery(AQueryString : String; AADOConnectionString : String) : String;
var
  ADOQuery: TADOQuery;
begin
  //Create empty ADO Query, then connect to connection string
  ADOQuery := TADOQuery.Create(nil);
  ADOQuery.ConnectionString:=AADOConnectionString;

  ADOQuery.SQL.Clear;
  ADOQuery.SQL.Add(AQueryString);
  ADOQuery.ExecSQL;

  ADOQuery.Open;

  //Set first query result and return first result
  ADOQuery.First;
  if(ADOQuery.Fields.Count > 0) then begin
    result:=ADOQuery.Fields[0].Value;
  end
  else begin
    result := '';
  end;
end;

我添加了字段计数,但我不确定这是否有帮助。基本上,如果没有结果,我想要result := ''

4

1 回答 1

12

您的代码片段中有一些问题:

  • 主要问题是您正在检查FieldCount. FieldCount将始终为非零,因为它包含您的查询返回的列数,无论您的查询是否返回记录。一种选择是检查RecordCount哪个代表返回的行数,但更好的选择是检查 标志。 EOF
  • 您正在泄漏 ADOQuery。始终使用try/finally块来创建和清理对象。
  • ExecSQL用于不返回记录集的查询(如 INSERT 和 DELETE),请Open改用
  • First之后无需使用Open
  • 如果您一遍又一遍地使用相同的查询,则最好使用参数,作为奖励,您的代码将更具可读性。

例子:

ADOQuery.SQL.Text := 'SELECT Cost FROM MaterialCost WHERE MaterialType = :MaterialType AND Thickness = :Thickness';
ADOQuery.Parameters.ParamByname('MaterialType').Value := 'MS';
ADOQuery.Parameters.ParamByname('Thickness').Value := 0.25;

你的功能代码应该是这样的:

function SelectOneQuery(const AQueryString, AADOConnectionString: string): string;
var
  ADOQuery: TADOQuery;
begin
  Result := '';

  ADOQuery := TADOQuery.Create(nil);
  try
    ADOQuery.ConnectionString := AADOConnectionString;
    ADOQuery.SQL.Text := AQueryString;
    ADOQuery.Open;
    if not ADOQuery.EOF then
      Result := ADOQuery.Fields[0].AsString;
  finally
    ADOQuery.Free;
  end;
end;
于 2013-09-16T21:26:09.427 回答