我使用MSSQL和ADO运行各种SQL语句。
代码序列如下所示:
aADOQuery.Active := False;
aADOQuery.SQL.Text := ' MY SQL STATEMENT ';
aADOQuery.ExecSQL;
aADOQuery.Active := True;
如果SQL返回结果为空,则最后一条语句失败。如何检查这种情况以避免运行时错误?
注意:SQL语句来自用户输入SQL的备忘录。
答案 0 :(得分:8)
如果您的查询返回记录集(SELECT
语句),则不使用ExecSQL
,而只需aADOQuery.Open
或Active := True
。
对于不返回记录集的查询,例如INSERT
/ UPDATE
/ DELETE
使用ExecSQL
。在大多数情况下,您会通过查询返回aADOQuery.RowsAffected
。
您应该使用ExecSQL
的其他SQL语句是CREATE
/ ALTER
/ DROP
/ EXEC
等...(否RowsAffected
在这种情况下返回)
如果查询未将光标返回到数据(例如INSERT
语句),则尝试Open
或将TDataSet
设置为Active
将失败。
您可以使用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;
答案 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;