2008-10-31 4 views
10

내 MS SQL 저장 프로 시저 중 일부는 'print'명령을 사용하여 메시지를 생성합니다. TADOConnection을 사용하여 MS SQL에 연결되는 Delphi 2007 응용 프로그램에서 'print'명령의 출력을 보려면 어떻게해야합니까?델파이에서 ADOConnection을 사용하여 'print'문의 출력보기

주요 요구 사항 : 1) 쿼리를 두 번 이상 실행할 수 없습니다. 그것은 물건을 업데이 트하는 수도 있습니다. 2) 데이터 세트가 반환 된 경우에도 '인쇄'결과를 확인해야합니다.

답변

9

재미있는 내용이었습니다 ...
ADOConnection의 OnInfoMessage 이벤트가 작동하지만 악마가 자세히 나와 있습니다!

주요 포인트 : = clUseServer 대신 기본 clUseClient의
사용의 CursorLocation.
ADOStoredProc에 ExecProc가 아닌 Open을 사용하십시오.
현재 사용중인 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을 만들기 Forms 응용 프로그램.
양식에 메모와 단추를 넣으십시오.

복사 다음 텍스트 카탈로그를 변경하고 데이터 소스와 ADOConnection에서의 OnInfoMessage에 양식에

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 

를 붙여 넣이 코드를 붙여 넣습니다 ButtonClick를 들어

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; 
+0

확실히 올바른 길을 찾아 왔습니다. 유연성을 위해 TADOStoredProc 대신 TADOCommand를 사용했으며 여전히 작동합니다. 또한 SET NOCOUNT ON은 선택 사항 인 것 같습니다. 가지고 있지 않으면 여분의 메시지 만 인쇄합니다.그리고 clUseServer는 TDBGrid에서 레코드 셋을 사용할 수 없도록 만듭니다. ( – apenwarr

+1

위의 OninfoMessage 코드는 첫 번째 PRINT 메시지 만 표시합니다. 모두를 인쇄하려면 (예 : SELECT 문 사이에 PRINT 문이 두 개 이상있는 경우) 이렇게하십시오. var i : 정수; 제가 위한 시작 -; cxMemo1.Lines.Add ( ADOConnection1.Errors.Item [I AdoConnection1.Errors.Count에 1 = 0이 // cxMemo1.Lines.Add (Error.Description)를 시작합니까 ] .Description); 끝; 끝; –

1

나는 그럴 수 없다고 생각합니다. 임시 테이블을 사용하여 인쇄 명령문을 덤프하고 그 결과와 함께 반환 할 수 있습니다.

3

.net의 연결 클래스에는 InfoMessage라는 이벤트가 있습니다. 이 이벤트의 핸들러에서 이벤트 args에서 InfoMessage (인쇄 명령문)를 검색 할 수 있습니다.

델파이에는 "OnInfoMessage"라는 유사한 이벤트가 있는데 도움이된다고 생각합니다.

+1

이것은 가깝습니다! command.ExecuteOptions = [eoExecuteNoRecords]로 설정하면 작동합니다. 하지만 그로 인해 데이터 세트를 가져올 수 없습니다. 흠 ... – apenwarr

0

Francois의 코드 (DXE2에서 테스트 됨)의 일부 기능이 추가되었습니다. 여러 개의 print 문과 다양한 수의 select 결과가 필요합니다. 변경 사항은 미묘합니다.

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; 
관련 문제