如何使用结果与Query处理ADO查询而没有结果?

时间:2013-03-31 15:24:35

标签: sql sql-server delphi ado

我使用MSSQL和ADO运行各种SQL语句。

代码序列如下所示:

aADOQuery.Active := False;
aADOQuery.SQL.Text := ' MY SQL STATEMENT ';
aADOQuery.ExecSQL;
aADOQuery.Active := True;

如果SQL返回结果为空,则最后一条语句失败。如何检查这种情况以避免运行时错误?

注意:SQL语句来自用户输入SQL的备忘录。

2 个答案:

答案 0 :(得分:8)

如果您的查询返回记录集(SELECT语句),则使用ExecSQL,而只需aADOQuery.OpenActive := True

对于不返回记录集的查询,例如INSERT / UPDATE / DELETE使用ExecSQL。在大多数情况下,您会通过查询返回aADOQuery.RowsAffected

您应该使用ExecSQL的其他SQL语句是CREATE / ALTER / DROP / EXEC等...(否RowsAffected在这种情况下返回)

如果查询未将光标返回到数据(例如INSERT语句),则尝试Open或将TDataSet设置为Active将失败。


您可以使用ADOConnection.Execute代替TADOQuery来执行命令文本,然后检查是否有RecordsetADOConnection返回。 在ADOConnection.OnExecuteComplete你可以做这样的事情:

procedure TForm1.ADOConnection1ExecuteComplete(Connection: TADOConnection;
  RecordsAffected: Integer; const Error: Error;
  var EventStatus: TEventStatus; const Command: _Command;
  const Recordset: _Recordset);
begin
  // check for errors
  if Assigned(Error) then
  begin        
    Memo1.Lines.Add('Error: ' + Error.Description);
  end;
  // check for a valid recordset
  if Assigned(Recordset) then
  begin
    MyDataSet.Recordset := Recordset; // MyDataSet is TADODataSet
  end;
  // check for affected rows
  if RecordsAffected >= 0 then
    Memo1.Lines.Add('Records affected: ' + IntToStr(RecordsAffected))
  else
    Memo1.Lines.Add('Record count: ' + IntToStr(MyDataSet.RecordCount));
end;

答案 1 :(得分:2)

虽然这不是您问题的直接答案,但我编写了一个SQL命令解释工具,它允许将各种命令发送到数据库。如果查询的第一个单词不是'select',那么'execsql'就是命令。对于'select',我确定查询是否是Borland所谓的实时查询,其中可以进行交互式编辑。我的程序中的'query'变量是一个TClientDataSet,它通过TDataSetProvider连接到TSQLDataSet,但这也适用于AdoQuery。

procedure TForm1.Button1Click(Sender: TObject);  // this is the 'execute query' button
var
 i: integer;
 cmd: string[6];
 tmp: string;

begin
 tmp:= mem.lines[0];
 i:= 1;
 while tmp[i] = ' ' do inc (i);
 dec (i);
 if i > 0 then tmp:= copy (tmp, i + 1, length (tmp) - i);
 cmd:= '';
 for i:= 1 to 6 do cmd:= cmd + upcase (tmp[i]);
 query.close;
 sdsquery.commandtext:= mem.text;
 if cmd = 'SELECT' then
  begin
   if livequery then
    begin
     dbgrid.options:= dbgrid.Options + [dgEditing];
     dbNavigator1.visiblebuttons:= [nbfirst, nbprior, nbNext, nbLast, nbInsert,
                                    nbDelete, nbedit, nbpost, nbcancel,
                                    nbrefresh];
    end
   else
    begin
     dbgrid.options:= dbgrid.Options - [dgEditing];
     dbNavigator1.visiblebuttons:= [nbfirst, nbprior, nbNext, nbLast];
    end;
   query.open
  end
 else sdsquery.ExecSQL;
end;

function TForm1.LiveQuery: boolean;
// check what the second token after 'from' is
const
 EOI = #26;

var
 cmdlen, curpos: integer;
 ch: char;
 tmp: string;

 Procedure GetChar;
 begin
  inc (curpos);
  if curpos <= cmdlen
   then ch:= mem.text[curpos]
   else ch:= EOI;
 end;

 Function Token: string;
 const
  punct: set of char = [' ', ',', ';', EOI, #10, #13];

 begin
  result:= '';
  while ch in punct do getchar;
  while not (ch in punct) do
   begin
    result:= result + upcase (ch);
    getchar
   end
 end;

begin
 ch:= ' ';
 cmdlen:= length (mem.text);
 curpos:= 0;
 tmp:= token;
 while tmp <> 'FROM' do tmp:= token;
 tmp:= token;  // this should be the first table name
 if ch = ',' then result:= false    // select ... from table1, table2
 else if ch = EOI then result:= true  // select * from table1
 else
  begin
   tmp:= token;
   result:= (tmp = 'WHERE') or (tmp = 'ORDER')
  end;
end;