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.
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:
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.
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.