我使用 MSSQL 和 ADO 运行各种 SQL 语句。
代码序列如下所示:
aADOQuery.Active := False;
aADOQuery.SQL.Text := ' MY SQL STATEMENT ';
aADOQuery.ExecSQL;
aADOQuery.Active := True;
如果 SQL 返回结果为空,则最后一条语句失败。如何检查这种情况以避免运行时错误?
注意:SQL 语句来自用户正在输入 SQL 的备忘录。
我使用 MSSQL 和 ADO 运行各种 SQL 语句。
代码序列如下所示:
aADOQuery.Active := False;
aADOQuery.SQL.Text := ' MY SQL STATEMENT ';
aADOQuery.ExecSQL;
aADOQuery.Active := True;
如果 SQL 返回结果为空,则最后一条语句失败。如何检查这种情况以避免运行时错误?
注意:SQL 语句来自用户正在输入 SQL 的备忘录。
如果您的查询返回一个记录集(SELECT
语句),则不应使用,ExecSQL
而应简单地使用aADOQuery.Open
or Active := True
。
对于不返回记录集的查询,例如INSERT
// UPDATE
,请DELETE
使用ExecSQL
. 在大多数情况下,您会收到aADOQuery.RowsAffected
您的查询。
您应该使用的其他 SQL 语句是ExecSQL
///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;
虽然这不是您问题的直接答案,但我编写了一个 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;