我的一些MS SQL存储过程使用'print'命令产生消息。在我使用TADOConnection连接到MS SQL的Delphi 2007应用程序中,如何查看这些“打印”命令的输出?使用Delphi中的ADOConnection查看“print”语句的输出
关键需求: 1)我无法多次运行查询;它可能会更新的东西。 2)即使数据集被返回,我也需要看到“打印”结果。
我的一些MS SQL存储过程使用'print'命令产生消息。在我使用TADOConnection连接到MS SQL的Delphi 2007应用程序中,如何查看这些“打印”命令的输出?使用Delphi中的ADOConnection查看“print”语句的输出
关键需求: 1)我无法多次运行查询;它可能会更新的东西。 2)即使数据集被返回,我也需要看到“打印”结果。
这是一个有趣的...
从ADOConnection的OnInfoMessage事件工作,但恶魔是在细节!
要点:
使用的CursorLocation =的clUseServer而不是默认的clUseClient。
在您的ADOStoredProc中使用Open而不是ExecProc。
使用NextRecordset从当前一个获得以下,但一定要检查你有一个打开。
在存储过程中使用SET NOCOUNT = ON。
SQL方面:存储过程
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
德尔福方:
创建一个新的VCL窗体应用程序。
在您的表单中放入备忘录和按钮。
复制下面的文本,改变目录和数据源并粘贴到您的表单
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
在的ADOConnection的OnInfoMessage把
Memo1.Lines.Add(Error.Description);
对于ButtonClick,粘贴此代码
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;
我不认为这是可能的。 您可以使用临时表来转储打印语句并将其与结果一起返回。
在.net的连接类中有一个名为InfoMessage的事件。在此事件的处理程序中,您可以从事件参数中检索InfoMessage(打印语句)。
我相信德尔福有一个类似的事件,称为“OnInfoMessage”,可以帮助你。
This is close!它工作,如果我设置command.ExecuteOptions = [eoExecuteNoRecords]。但是这阻止了我获取任何数据集。嗯...... – apenwarr 2008-10-31 20:13:08
对Francois的代码进行了一些增强(使用DXE2进行测试)以配合用于多个打印语句以及来自可变数量选择的结果。这些变化很微妙。
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;
这绝对会让我走上正轨:为了获得灵活性,我使用了TADOCommand而不是TADOStoredProc,它仍然有效。 SET NOCOUNT ON也似乎是可选的:如果您没有它,它只会打印额外的消息。并且clUseServer使记录集在TDBGrid中不可用:( – apenwarr 2008-11-03 17:58:02