Announcement

Collapse
No announcement yet.

Recordset + StorProc

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Recordset + StorProc

    Hallo, <br>
    wir bekomme ich die Daten einer StorProc in RecordSet.
    Bei ADO-Express setze ich dazu die Eigenschaft CommandType.
    Wie formuliere ich das bei einem RecordSet.<br>
    Helmut

  • #2
    Hallo,

    angenommen, in einer SQL Server-Datenbank wurde die folgende Stored Procedure untergebracht:
    <pre>
    CREATE PROCEDURE GetAdrFromID
    @iID INTEGER
    AS
    SELECT Vorname, Name, Ort, eMail
    FROM LONGFETCH WITH(NOLOCK)
    WHERE ID = @iID
    -- Anzahl der Treffer als Rückgabewertg weitergeben
    Return @@ROWCOUNT
    </pre>
    Über den direkten Zugriff auf die ADO-Objekte (d.h. Verzicht auf ADO Express) kann diese SP aufgerufen werden:
    <pre>
    procedure TForm1.DoNativeGetAdrFromID;
    var
    aConnection : _Connection;
    aCommand : _Command;
    aParam : _Parameter;
    aRecordset : _Recordset;
    vID : Variant;
    vData : Variant;
    i : Integer;
    swConnStr : WideString;
    begin
    swConnStr := DataModule1.ADOConnection1.ConnectionString;
    // Instanz vom Connection-Objekt anfordern
    aConnection := CoConnection.Create;
    aConnection.Open(swConnStr, '', '', adConnectUnspecified);
    // Instanz vom Command-Objekt anfordern
    aCommand := CoCommand.Create;
    with aCommand do
    begin
    Set_ActiveConnection(aConnection);
    CommandType := adCmdStoredProc;
    Set_CommandText('GetAdrFromID');
    aParam := CreateParameter('RETURN_VALUE', adInteger, adParamReturnValue,
    4, EmptyParam);
    Parameters.Append(aParam);
    vID := 1;
    aParam := CreateParameter('@iID', adInteger, adParamInput, 4, vID);
    Parameters.Append(aParam);
    end;
    // Instanz vom RecordSet-Objekt anfordern
    aRecordset := CoRecordSet.Create;
    try
    FStartTick := GetTickCount;
    for i := 0 to FLoop do
    begin
    vID := i + 1;
    aRecordset.Open(aCommand, EmptyParam, adOpenStatic, adLockReadOnly,
    adCmdStoredProc);
    { Anstelle des Zugriffs über den Interface-Zeiger des Field-Objekts
    vData := aRecordset.Fields[0].Value;
    ist der direkte Zugriff auf die RecordSet-Methode Collect immer
    dann schneller, wenn nur der Wert des Feldes ausgelesen werden
    soll }
    vData := aRecordset.Collect[0];
    if not VarIsNull(vData) then
    StaticTextVorname.Caption := vData;
    vData := aRecordset.Collect[1];
    if not VarIsNull(vData) then
    StaticTextName.Caption := vData;
    vData := aRecordset.Collect[2];
    if not VarIsNull(vData) then
    StaticTextOrt.Caption := vData;
    vData := aRecordset.Collect[3];
    if not VarIsNull(vData) then
    StaticTextEMail.Caption := vData;
    aRecordset.Close;
    ProgressBar1.StepIt;
    end;
    FStopTick := GetTickCount;
    LogData('Native ADO GetAdrFromID ');
    finally
    aRecordset := nil;
    aCommand := nil;
    aConnection.Close;
    end;
    end;
    </pre&gt

    Comment


    • #3
      Hallo,<br>
      ich habe folgende Formulierung<br>
      aADOConnection := CoConnection.Create;<br>
      aADOConnection.Set_CommandTimeout(150);<br>
      aADODataSet := CoRecordSet.Create;<br>
      aADODataSet.Set_CursorLocation(adUseServer);<br>
      aADOConnection.Open('Provider=MSDAORA.1;Password=' + szPassword + ';User ID=' + szUserName + ';Data Source=' + szConnectString + ';Extended Properties="PLSQLRSet=1"','','',0);<br>

      aADODataSet.Open('adsldb.SP_DQ.ST7_AUSLESEN', aADOConnection, adOpenForwardOnly, adLockReadOnly, adCmdStoredProc);<br>
      aADODataSet.MoveFirst;<br>
      diese geht auch oder?<br>
      <br>
      aber wo bringe ich denn soetwas unter?<br>
      aADODataSet. <b>"ExecuteOptions := [adAsyncFetchNonBlocking];"</b><br>
      <br>
      und wie frage ich ein Error ab?<br>
      Helmu

      Comment


      • #4
        Hallo<br>
        und noch eine Frage: Kann "Collect" nur über den Index abgefragt werden?<br>
        Helmu

        Comment


        • #5
          Hallo,

          im MDAC-SDK wird die RecordSet-Methode <b>Open</b> folgendermassen beschrieben:
          <pre>
          recordset.Open Source, ActiveConnection, CursorType, LockType, Options
          </pre>
          Und als Kommentar für den letzten Parameter <b>Options</b> wird dort folgendes aufgeführt: "<i>Options: Optional. A Long value that indicates how the provider should evaluate the Source argument if it represents something other than a Command object, or that the Recordset should be restored from a file where it was previously saved. Can be one or more <b>CommandTypeEnum</b> or <b>ExecuteOptionEnum</b> values, which can be combined with a bitwise AND operator. <br>
          Note: If you open a Recordset from a Stream containing a persisted Recordset, using an ExecuteOptionEnum value of adAsyncFetchNonBlocking will not have an effect; the fetch will be synchronous and blocking.<br>
          The ExecuteOpenEnum values of adExecuteNoRecords or adExecuteStream should not be used with Open.</i>"

          Eine OleException wird in Delphi wie jede andere Exception auch über einen Try..Except-Block abgefangen. Dort kann dann die Kollektion <b>Errors</b> des <b>Connection</b>-Objekts ausgewertet werden:
          <pre>
          ....
          with aConnection.Errors do
          for iIdx := 0 to (Count - 1) do
          with Item[iIdx] do
          if not ((iIdx > 0) and (NativeError = 3621)) then
          sErrMsg := sErrMsg +
          ' Error #' + IntToStr(iIdx) + ':' + CRLF +
          ' Description: ' + Description + CRLF +
          ' Number: ' + IntToStr(Number) + CRLF +
          ' Native: ' + IntToStr(NativeError) + CRLF +
          ' Source: ' + Source + CRLF +
          ' State: ' + SQLState + CRLF + CRLF;
          ...
          </pre>
          Der Zugriff über <b>Collect</b> wurde von Microsoft zur Performance-Steigerung eingebaut, daher wird nur der schnellste Zugriffsweg (Index) unterstützt. Man kann aber auch selbstverständlich den Weg über die <b>Fields</b>-Kollektion gehen, und jedes Feldobjekt einzeln abfordern.
          &#10

          Comment


          • #6
            Hallo<br>
            und noch eine Frage: Kann "Collect" nur über den Index abgefragt werden?<br>
            Helmu

            Comment


            • #7
              Ja - siehe den vorletzten Satz meiner vorherigen Antwort

              Comment


              • #8
                Hallo Andreas,

                du hast in Deinem Posting die Variable "FStartTick" benutzt. Als was muß ich diese Variable definieren ?

                In Deinem Buch "Interbase mit Delphi" wird in einem Beispiel ebenfalls diese Variable verwendet.

                Kannst Du bitte etwas zur Theorie der Zeitmessung sagen ?

                Grüsse,
                Carste

                Comment


                • #9
                  Hallo,

                  &gt;..Variable "FStartTick" benutzt..

                  diese INTEGER-Variablen dienen nur zur Zeitmessung über die Win32-API-Funktion GetTickCount und können daher ersatzlos entfernt werden. Die API-Funktion GetTickCount liefert die Millisekundenanzahl seit dem Systemstart zurück, allerdings mit der Ungenauigkeit des System-Timers der verwendeten Hardware. Es handelt sich also nur um einen ungefähren Wert.

                  Wenn es ganz genau sein soll, hilft die Win32-API-Funktion <b>QueryPerformanceCounter</b> oder der Multimedia-Timer (<i>timeBeginPeriod</i> und <i>timeEndPeriodweiter</i>) weiter

                  Comment

                  Working...
                  X