2

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

代码序列如下所示:

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

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

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

4

2 回答 2

8

如果您的查询返回一个记录集(SELECT语句),则不应使用ExecSQL而应简单地使用aADOQuery.Openor Active := True

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

您应该使用的其他 SQL 语句是ExecSQL///CREATE等...(ALTER在这种情况下不返回DROPEXECRowsAffected

如果查询没有将游标返回到数据(例如INSERT语句),则尝试Open或设置此类TDataSetActive失败。


您可以使用ADOConnection.Execute而不是TADOQuery执行命令文本,然后检查是否有有效Recordset的从ADOConnection. 在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;
于 2013-03-31T15:33:48.577 回答
2

虽然这不是您问题的直接答案,但我编写了一个 SQL 命令解释器工具,它允许将各种命令发送到数据库。如果查询的第一个单词不是“select”,那么“execsql”就是命令。对于“选择”,我确定了查询是否是 Borland 所说的实时查询,其中可以进行交互式编辑。我的程序中的“查询”变量是一个 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;
于 2013-03-31T17:01:19.193 回答