¿Cómo se maneja la consulta ADO con los resultados en comparación con la consulta sin resultados?

Ejecuto varias declaraciones SQL usando MSSQL y ADO.

La secuencia de código se ve así:

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

La última instrucción falla si el resultado del retorno de SQL está vacío. ¿Cómo verificar este caso para evitar errores de time de ejecución?

Nota: La statement SQL proviene de una nota donde el usuario está escribiendo el SQL.

Si su consulta devuelve un set de loggings ( SELECT ) no debe usar ExecSQL sino simplemente aADOQuery.Open o Active := True .

Para las consultas que no devuelven un set de loggings, por ejemplo INSERT / UPDATE / DELETE , utilice ExecSQL . en la mayoría de los casos, aADOQuery.RowsAffected a aADOQuery.RowsAffected por tu consulta.

Otras sentencias de SQL que debe usar ExecSQL son CREATE / ALTER / DROP / EXEC etc … (no RowsAffected devolución de RowsAffected en este caso)

Si la consulta no devuelve un cursor a los datos (como la INSERT ), se producirá un error al tratar de Open o establecer dicho TDataSet en Active .


Puede usar ADOConnection.Execute lugar de TADOQuery para ejecutar su text de command, y luego inspeccionar si hay un Recordset válido que regresa de ADOConnection . En ADOConnection.OnExecuteComplete tu podrías hacer algo como esto:

 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; 

Si bien esta no es una respuesta directa a su pregunta, escribí una herramienta de intérprete de commands SQL que permite el envío de varios commands a la database. Si la primera palabra de la consulta no es 'seleccionar', entonces 'execsql' es el command. Para 'seleccionar', determiné si la consulta era lo que Borland llama una consulta en vivo, en la cual la edición interactiva es posible. La variable 'query' en mi progtwig es un TClientDataSet que está conectado a través de un TDataSetProvider a un TSQLDataSet, pero esto también debería funcionar con 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;