Das war ein interessantes ...
Das OnInfoMessage-Ereignis von der ADOConnection funktioniert, aber der Teufel steckt im Detail!
Hauptpunkte:
Verwendung Cursor = clUseServer anstelle des Standard-clUseClient.
Verwenden Sie Open und nicht ExecProc mit Ihrem ADOStoredProc.
Verwenden Sie NextRecordset aus dem aktuellen, um Folgendes zu erhalten, aber stellen Sie sicher, dass Sie eines geöffnet haben.
Verwenden Sie SET NOCOUNT = ON in Ihrer gespeicherten Prozedur.
SQL-Seite: gespeicherten Prozedur
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
Delphi Seite:
eine neue VCL-Formularanwendung erstellen.
Setzen Sie ein Memo und eine Schaltfläche in Ihr Formular.
Kopieren Sie den folgenden Text, ändern Sie den Katalog und Datenquelle und fügen Sie ihn in das Formular
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
Im OnInfoMessage des ADOConnection setzen
Memo1.Lines.Add(Error.Description);
Für die Button, diesen Code und fügen
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;
Das hat mich definitiv auf den richtigen Weg gebracht: Aus Gründen der Flexibilität habe ich einen TADOCommand anstelle eines TADOStoredProc verwendet, und es funktioniert immer noch. Das SET NOCOUNT ON scheint auch optional zu sein: Es druckt nur zusätzliche Nachrichten, wenn Sie es nicht haben.Und clUseServer macht die Recordsets in einem TDBGrid unbrauchbar :( – apenwarr
Der OninfoMessage-Code oben zeigt nur die erste PRINT-Nachricht. Um sie alle zu drucken (zB wenn es mehr als 1 PRINT-Anweisungen zwischen den SELECT-Anweisungen gibt): var integer; für i beginnen: = 0 bis AdoConnection1.Errors.Count - 1 do // cxMemo1.Lines.Add (Error.Description) beginnen; cxMemo1.Lines.Add ( ADOConnection1.Errors.Item [i ]. Beschreibung); Ende; Ende; –