Announcement

Collapse
No announcement yet.

DELPHI5P: SQL-Abfrage abbrechen

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

  • DELPHI5P: SQL-Abfrage abbrechen

    Hallo Delphianer,
    im Eifer des Gefechtes kommt es mal vor, daß ich die SQL-Abfrage nicht korrekt formuliert habe. Dann ist der Rechner erstmal minutenlang beschäftigt.
    Welche Möglichkeiten habe ich, die Abfrage mittels eines 'Abbrechen'-Buttons, abzubrechen ?

    MfG
    Uwe

  • #2
    Hallo,

    wenn ADO eingesetzt wird, gibt es eine offizielle Möglichkeit (RecordSet-Methode <b>Cancel</b>). Wenn der Zugriff über die BDE erfolgt, kann man eine langlaufende Abfrage über einen BDE-Callback (<b>OnServerYield</b>) abwürgen, auch wenn dies offiziell so nicht dokumentiert wird

    Comment


    • #3
      Hallo,
      ich frage mehrere PARADOX-Tabellen per SQL ab. Sie gaben mir den Tip mit dem BDE-Callback (OnServerYield). Im Internet habe ich den folgenden Code gefunden.

      procedure TForm1.Query1ServerYield(DataSet: TDataSet;
      var AbortQuery: Boolean);
      begin
      AbortQuery:=Abbruch;
      Application.processmessages;
      end;

      Nur wie kann ich diese Prozedur aufrufen, wenn die Abfrage läuft (Sanduhr) ? Es gibt keine Reaktion auf Maus-, Timer- oder Tastenaktionen.
      Mf

      Comment


      • #4
        Hallo,

        das folgende Beispiel für den Abbruch einer langen SQL-Abfrage stammt aus meinen Buch <i>Delphi 3 Datenbankentwicklung</i>:
        <pre>
        unit YieldFrm;

        interface

        uses
        Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
        StdCtrls, Buttons, Grids, DBGrids, DB, DBTables, ExtCtrls;

        type
        TFormMain = class(TForm)
        QueryTest: TQuery;
        DataSourceTest: TDataSource;
        DBGrid1: TDBGrid;
        BitBtnStart: TBitBtn;
        Bevel1: TBevel;
        LabelYieldCount: TLabel;
        BitBtnAbort: TBitBtn;
        procedure BitBtnStartClick(Sender: TObject);
        procedure QueryTestServerYield(DataSet: TDataSet; var AbortQuery: Boolean);
        procedure BitBtnAbortClick(Sender: TObject);
        private
        { Private-Deklarationen }
        iCnt : Integer; // OnServerYield-Ereignisse mitzählen
        bSQLAbort : Boolean; // soll abgebrochen werden ?
        public
        { Public-Deklarationen }
        end;

        var
        FormMain: TFormMain;

        implementation

        {$R *.DFM}

        {
        Die TQuery-Instanz startet die folgende, längerdauernde SQL-Abfrage :
        SELECT ort, COUNT(ort)
        FROM "callback.dbf"
        GROUP BY ort
        ORDER BY ort
        Durch die GROUP BY und ORDER BY legt die BDE temporäre DBF-
        Tabellen an, daher dauert die Abfrage auch auf einem schnellen
        Rechner etwas länger.
        Zur Kontrolle informiert ein TLabel über die eingetroffenen OnServerYield-Ereignisse.
        Klickt der Anwender den Abbruch-Button an, so wird die Abfrage gestoppt.
        Normalerweise ist OnServerYield für den SQL-Server der Firma
        Sybase gedacht, es funktioniert aber anscheindend auch mit
        normalen Desktop-Datenbanktabellen.
        }

        procedure TFormMain.BitBtnStartClick(Sender: TObject);
        begin
        iCnt := 0;
        bSQLAbort := False;
        QueryTest.Active := False;
        BitBtnStart.Enabled := False;
        try
        try
        QueryTest.Open
        except
        on E:EDBEngineError do
        // Fehler 10756 = Fähigkeit nicht vorhanden
        if E.Errors[0].ErrorCode = 10756
        then MessageBeep(0) // Abort
        else raise // andere Fehler anzeigen
        end
        finally
        BitBtnStart.Enabled := True
        end
        end;

        {
        Das Ereignis »OnServerYield« implementiert einen Standard-
        Callback-Aufruf der BDE. Auszug aus DBTables.pas :

        function TBDEDataSet.YieldCallBack(CBInfo: Pointer): CBRType;
        var
        AbortQuery: Boolean;
        begin
        AbortQuery := False;
        if Assigned(OnServerYield) and (FCBYieldStep <> cbYieldLast)
        then OnServerYield(Self, AbortQuery);
        if AbortQuery then
        Result := cbrABORT else
        Result := cbrUSEDEF;
        end;
        }

        procedure TFormMain.QueryTestServerYield(DataSet: TDataSet;
        var AbortQuery: Boolean);
        begin
        Inc(iCnt);
        // Anzahl der OnServerYield-Ereignisse mitzählen
        LabelYieldCount.Caption := Format(' %d OnServerYield-Ereignisse',
        [iCnt]);
        // Anzeige im Formular aktualisieren
        Update;
        // Auswertung des Abbruch-Buttons ermöglichen
        Application.ProcessMessages;
        // Weitermachen oder nicht weitermachen - das ist hier die Frage
        AbortQuery := bSQLAbort
        end;

        { Anwender kann langandauernde SQL-Abfrage abbrechen }

        procedure TFormMain.BitBtnAbortClick(Sender: TObject);
        begin
        bSQLAbort := True
        end;

        end.
        </pre&gt

        Comment


        • #5
          Hallo,
          ich habe Ihr Buch 'Client/Server Datenbankentwicklung mit Delphi. Nur das Beispiel 'unit YieldFrm;' habe ich nicht darin gefunden. Auch nicht auf der Diskette. Deshalb habe ich eine neue Anwendung genommen und Ihren Sourcecode implementiert.

          Ich habe aber noch immer das Problem, daß während der Abfrage (Sanduhr läuft) der Abbruch-Button nicht reagiert. Wie soll das eigentlich funktionieren und welches Ereignis von QueryTest ruft die Prozedur 'QueryTestServerYield' auf ?

          Mfg.
          Uw

          Comment


          • #6
            Hallo,

            da es sich um einen <B>BDE-Callback</b> handelt, wird diese Ereignisbehandlungsmethode von der BDE aus aufgerufen. In meinem o.g. Beispiel taucht im Kommentar die folgende Anweisung in der Implementierung von <b>TBDEDataSet.YieldCallBack</b> auf:
            <pre>
            if Assigned(OnServerYield) and (FCBYieldStep <> cbYieldLast)
            then OnServerYield(Self, AbortQuery);
            </pre>
            Wenn es eine Ereignisbehandlungsmethode für OnServerYield gibt, wird diese von dem Vorfahren TBDEDataSet auch aufgerufen.

            Damit der Abbruch-Button ausgewertet werden kann, taucht innerhalb meiner Ereignisbehandlungsmethode die Zeile <b>Application.ProcessMessages</b> auf. Somit kann die zweite Ereignisbehandlungsmethode für das Anklicken des Abbruch-Button sdie Variable <b>bSQLAbort</b> auf True setzen, so dass die Ereignisbehandlungsmethode für OnServerYield diese Variable auswerten kann und bei Bedarf abbrechen kann.

            Um zu prüfen, ob die BDE-Callbacks tatsächlich ausgelöst werden, würde ich an Ihrer Stelle zuerst einen <b>MessageBeep</b>-Aufruf in die Ereignisbehandlungsmethode für OnServerYield einfügen. Wenn nichts zu hören ist, löst die BDE aus irgend einem Grund keinen Callback-Aufruf aus

            Comment


            • #7
              Hallo,
              ich habe DELPHI5P und da gibt es in der Datei DBTables.pas keine Funktion 'YieldCallBack'.
              In Ihrer letzten Message verweisen Sie auf Ihr Buch 'Datenbankentwicklungen'. Ich habe Ihr Buch 'Client/Server Datenbankentwicklung mit Delphi'. Nur in diesem Buch ist nicht das Beispiel YIELDFRM. Oder geht es um ein anderes Buch ?
              Sie würden mir einen großen Gefallen tun, wenn Sie mir Ihr Beispiel YIELDFRM per eMail senden würden.
              [email protected]

              Comment


              • #8
                Hallo,

                in meiner Antwort vom 27.3. habe ich in der ersten Zeile darauf hingewiesen, dass das Beispiel aus meinem <i>Delphi 3 Datenbankentwicklung</i> stammt, und daher auch mit <b>Delphi 3</b> geschrieben wurde. Ich habe nicht nachgesehen, ob alles bei Delphi 5 noch an der alten Stelle ist, aber ein BDE-Callback kann ja jederzeit im eigenen Programm mit wenigen Programmzeilen aktiviert werden, so dass sich alles fehlende nachrüsten lässt.

                Das Delphi 3-Beispielprojekt füge ich als Download bei

                Comment

                Working...
                X