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;