代码之家  ›  专栏  ›  技术社区  ›  apenwarr

在Delphi中使用ADOConnection查看“print”语句的输出

  •  10
  • apenwarr  · 技术社区  · 16 年前

    我的一些MS SQL存储过程使用“print”命令生成消息。在我的Delphi2007应用程序中,它使用TADOConnection连接到MS SQL,如何查看这些“打印”命令的输出?

    关键要求: 2) 即使返回数据集,我也需要查看“打印”结果。

    4 回复  |  直到 16 年前
        1
  •  9
  •   Francesca    16 年前


    来自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
    

    在ADO连接的OnInfo消息中

    Memo1.Lines.Add(Error.Description);
    

    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;
    
        2
  •  3
  •   AlexCuse    16 年前

    我相信Delphi有一个类似的事件叫做“OnInfoMessage”,它将帮助您。

        3
  •  1
  •   shahkalpesh    16 年前

    我认为那是不可能的。

        4
  •  0
  •   Freddie bell    12 年前

    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;