web-dev-qa-db-ger.com

Ergebnismengen in MySQL durchlaufen

Ich versuche, eine gespeicherte Prozedur in MySQL zu schreiben, die eine ziemlich einfache Auswahlabfrage ausführt, und dann die Ergebnisse in einer Schleife durchzugehen, um zu entscheiden, ob zusätzliche Abfragen, Datentransformationen oder die Daten insgesamt verworfen werden sollen. Eigentlich möchte ich Folgendes implementieren:

$result = mysql_query("SELECT something FROM somewhere WHERE some stuff");
while ($row = mysql_fetch_assoc($result)) {
    // check values of certain fields, decide to perform more queries, or not
    // tack it all into the returning result set
}

Nur, ich möchte es nur in MySQL, so kann es als Prozedur aufgerufen werden. Ich weiß, dass es für Trigger die Syntax FOR EACH ROW ... Gibt, aber ich kann nichts Vergleichbares für die Verwendung außerhalb der Syntax CREATE TRIGGER ... Finden. Ich habe einige der Schleifenmechanismen in MySQL durchgelesen, aber bis jetzt kann ich mir nur vorstellen, dass ich so etwas implementieren würde:

SET @S = 1;
LOOP
    SELECT * FROM somewhere WHERE some_conditions LIMIT @S, 1
    -- IF NO RESULTS THEN
    LEAVE
    -- DO SOMETHING
    SET @S = @S + 1;
END LOOP

Obwohl selbst dies in meinem Kopf etwas verschwommen ist.

Obwohl dies meiner Meinung nach nicht unbedingt relevant ist, werden bei der ersten Abfrage vier Tabellen zu einem Modell hierarchischer Berechtigungen zusammengefügt. Auf der Grundlage der Kettenlänge einer bestimmten Berechtigung werden dann zusätzliche Informationen zu abgerufen die Kinder, an die diese Erlaubnis vererbt werden soll.

54
Dereleased

Etwas wie dieses sollte den Trick machen (Lesen Sie jedoch nach dem Snippet für weitere Informationen)

CREATE PROCEDURE GetFilteredData()
BEGIN
  DECLARE bDone INT;

  DECLARE var1 CHAR(16);    -- or approriate type
  DECLARE Var2 INT;
  DECLARE Var3 VARCHAR(50);

  DECLARE curs CURSOR FOR  SELECT something FROM somewhere WHERE some stuff;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET bDone = 1;

  DROP TEMPORARY TABLE IF EXISTS tblResults;
  CREATE TEMPORARY TABLE IF NOT EXISTS tblResults  (
    --Fld1 type,
    --Fld2 type,
    --...
  );

  OPEN curs;

  SET bDone = 0;
  REPEAT
    FETCH curs INTO var1,, b;

    IF whatever_filtering_desired
       -- here for whatever_transformation_may_be_desired
       INSERT INTO tblResults VALUES (var1, var2, var3 ...);
    END IF;
  UNTIL bDone END REPEAT;

  CLOSE curs;
  SELECT * FROM tblResults;
END

Ein paar Dinge zu beachten ...

Zum obigen Snippet:

  • möglicherweise möchten Sie einen Teil der Abfrage an die gespeicherte Prozedur übergeben, insbesondere die Suchkriterien, um sie allgemeiner zu gestalten.
  • Wenn diese Methode von mehreren Sitzungen usw. aufgerufen werden soll, möchten Sie möglicherweise eine Sitzungs-ID übergeben, um einen eindeutigen temporären Tabellennamen zu erstellen (eigentlich unnötige Bedenken, da verschiedene Sitzungen nicht denselben temporären Dateinamensraum verwenden; siehe Kommentar von Gruber weiter unten )
  • Einige Teile wie die Variablendeklarationen, die SELECT-Abfrage usw. müssen ordnungsgemäß angegeben werden

Allgemeiner: versucht, die Verwendung eines Cursors zu vermeiden.

Ich habe die Cursor-Variable absichtlich curs [e] genannt, weil Cursor ein gemischter Segen sind. Sie können uns helfen, komplizierte Geschäftsregeln zu implementieren, die in der deklarativen Form von SQL möglicherweise schwierig auszudrücken sind. Dann werden wir jedoch dazu gebracht, die prozedurale (imperative) Form von SQL zu verwenden, eine allgemeine Funktion von SQL, die weder sehr benutzerfreundlich noch sehr benutzerfreundlich ist. ausdrucksstark, programmtechnisch und in Bezug auf die Leistung oft weniger effizient.

Vielleicht können Sie die gewünschte Transformation und Filterung im Kontext einer "einfachen" (deklarativen) SQL-Abfrage ausdrücken.

74
mjv

Verwenden Sie Cursor.

Ein Cursor kann beim Lesen eines Dokuments wie ein gepufferter Leser betrachtet werden. Wenn Sie sich jede Zeile als eine Zeile in einem Dokument vorstellen, würden Sie die nächste Zeile lesen, Ihre Operationen ausführen und dann den Cursor vorrücken.

4
AlishahNovin