variable una procedimiento print permite mostrar mensajes mensaje error ejemplos devolver declaraciĆ³n datos capturar asignaciĆ³n almacenado sql-server delphi stored-procedures ado

sql-server - una - raiserror sql server ejemplos



Ver el resultado de las declaraciones ''print'' usando ADOConnection en Delphi (4)

Algunos de mis procedimientos almacenados de MS SQL producen mensajes usando el comando ''imprimir''. En mi aplicación Delphi 2007, que se conecta a MS SQL usando TADOConnection, ¿cómo puedo ver el resultado de esos comandos ''imprimir''?

Requisitos clave: 1) No puedo ejecutar la consulta más de una vez; podría estar actualizando cosas. 2) Necesito ver los resultados de ''impresión'' incluso si se devuelven conjuntos de datos.


En las clases de conexión de .net hay un evento llamado InfoMessage. En un controlador para este evento, puede recuperar InfoMessage (declaraciones de impresión) desde los argumentos del evento.

Creo que Delphi tiene un evento similar llamado "OnInfoMessage" que podría ayudarte.


No creo que eso sea posible. Puede usar una tabla temporal para volcar las declaraciones de impresión y devolverlas junto con los resultados.


Esa fue una interesante ...
El evento OnInfoMessage de ADOConnection funciona pero ¡el Demonio está en los detalles!

Puntos principales:
use CursorLocation = clUseServer en lugar del clUseClient predeterminado.
utilice Open y no ExecProc con su ADOStoredProc.
use NextRecordset del actual para obtener lo siguiente, pero asegúrese de verificar que tenga uno abierto.
use SET NOCOUNT = ON en su procedimiento almacenado.

Lado SQL: su procedimiento almacenado

SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N''[dbo].[FG_TEST]'') AND type in (N''P'', N''PC'')) DROP PROCEDURE [dbo].[FG_TEST] GO -- ============================================= -- Author: François -- Description: test multi ADO with info -- ============================================= CREATE PROCEDURE FG_TEST AS BEGIN -- SET NOCOUNT ON absolutely NEEDED SET NOCOUNT ON; PRINT ''*** start ***'' SELECT ''one'' as Set1Field1 PRINT ''*** done once ***'' SELECT ''two'' as Set2Field2 PRINT ''*** done again ***'' SELECT ''three'' as Set3Field3 PRINT ''***finish ***'' END GO

Lado Delphi:
Crea una nueva aplicación de formularios VCL.
Ponga un Memo y un botón en su formulario.

Copie el siguiente texto, cambie el catálogo y el origen de datos y péguelo en su formulario

object ADOConnection1: TADOConnection ConnectionString = ''Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security In'' + ''fo=False;Initial Catalog=xxxYOURxxxDBxxx;Data Source=xxxYOURxxxSERVERxxx'' CursorLocation = clUseServer LoginPrompt = False Provider = ''SQLOLEDB.1'' OnInfoMessage = ADOConnection1InfoMessage Left = 24 Top = 216 end object ADOStoredProc1: TADOStoredProc Connection = ADOConnection1 CursorLocation = clUseServer ProcedureName = ''FG_TEST;1'' Parameters = <> Left = 24 Top = 264 end

En el OnInfoMessage de ADOConnection put

Memo1.Lines.Add(Error.Description);

Para el ButtonClick, pega este código

procedure TForm1.Button1Click(Sender: TObject); const adStateOpen = $00000001; // or defined in ADOInt var I: Integer; ARecordSet: _Recordset; begin Memo1.Lines.Add(''==========================''); ADOStoredProc1.Open; // not ExecProc !!!!! ARecordSet := ADOStoredProc1.Recordset; while Assigned(ARecordSet) do begin // do whatever with current RecordSet while not ADOStoredProc1.Eof do begin Memo1.Lines.Add(ADOStoredProc1.Fields[0].FieldName + '': '' + ADOStoredProc1.Fields[0].Value); ADOStoredProc1.Next; end; // switch to subsequent RecordSet if any ARecordSet := ADOStoredProc1.NextRecordset(I); if Assigned(ARecordSet) and ((ARecordSet.State and adStateOpen) <> 0) then ADOStoredProc1.Recordset := ARecordSet else Break; end; ADOStoredProc1.Close; end;


Algunas mejoras en el código de Francois (como se probó con DXE2) para atender múltiples declaraciones de impresión y los resultados de un número variable de selecciones. Los cambios son sutiles.

procedure TForm1.ADOConnection1InfoMessage(Connection: TADOConnection; const Error: Error; var EventStatus: TEventStatus); var i: integer; begin // show ALL print statements for i := 0 to AdoConnection1.Errors.Count - 1 do begin // was: cxMemo1.Lines.Add(Error.Description); cxMemo1.Lines.Add( ADOConnection1.Errors.Item[i].Description); end; end; procedure TForm1.cxButton1Click(Sender: TObject); const adStateOpen = $00000001; // or uses ADOInt var records: Integer; ARecordSet: _RecordSet; begin cxMemo1.Lines.Add(''==========================''); ADOStoredProc1.Open; try ARecordSet := ADOStoredProc1.RecordSet; // initial fetch while Assigned(ARecordSet) do begin // assign the recordset to a DataSets recordset to traverse AdoDataSet1.Recordset := ARecordSet; // do whatever with current ARecordSet while not ADODataSet1.eof do begin cxMemo1.Lines.Add(ADODataSet1.Fields[0].FieldName + '': '' + ADODataSet1.Fields[0].Value); AdoDataSet1.Next; end; // fetch next recordset if there is one ARecordSet := ADOStoredProc1.NextRecordSet(records); if Assigned(ARecordSet) and ((ARecordSet.State and adStateOpen) <> 0) then ADOStoredProc1.Recordset := ARecordSet else Break; end; finally ADOStoredProc1.Close; end; end;