J'essaie d'écrire une procédure stockée dans MySQL qui effectuera une requête de sélection assez simple, puis de survoler les résultats afin de décider s'il convient d'exécuter des requêtes supplémentaires, des transformations de données ou de les supprimer complètement. En fait, je veux implémenter ceci:
$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
}
Seulement, je le veux seulement dans MySQL, donc ça peut être appelé comme une procédure. Je sais que pour les déclencheurs, il y a le FOR EACH ROW ...
_ syntaxe, mais je ne trouve aucune mention de ce genre pour une utilisation en dehors de la CREATE TRIGGER ...
syntaxe. J'ai lu quelques-uns des mécanismes de bouclage de MySQL, mais jusqu'à présent, tout ce que je peux imaginer, c'est que j'implémenterais quelque chose comme ceci:
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
Même si cela reste un peu flou dans mon esprit.
Pour référence, bien que je ne pense pas que ce soit nécessairement pertinent, la requête initiale associera quatre tables pour former un modèle d'autorisations hiérarchiques, puis en fonction du niveau de la chaîne d'une autorisation spécifique, elle récupérera des informations supplémentaires sur les enfants à qui cette permission devrait être héritée.
Quelque chose comme cela devrait faire l'affaire (Cependant, lisez après l'extrait pour plus d'informations)
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
Quelques points à considérer ...
En ce qui concerne l'extrait ci-dessus:
Plus généralement: en essayant d'éviter d'avoir besoin d'un curseur.
J'ai volontairement appelé la variable curseur curs [e], car les curseurs sont une bénédiction mixte. Ils peuvent nous aider à implémenter des règles métier compliquées qu'il peut être difficile d'exprimer sous la forme déclarative de SQL, mais cela nous amène ensuite à utiliser la forme procédurale (impérative) de SQL, qui est une caractéristique générale de SQL qui n'est pas très conviviale/expressif, en termes de programmation et souvent moins efficace en termes de performances.
Peut-être pourriez-vous chercher à exprimer la transformation et le filtrage souhaités dans le contexte d'une requête SQL "simple" (déclarative).
Utilisez les curseurs.
Un curseur peut être considéré comme un lecteur protégé lors de la lecture d’un document. Si vous considérez chaque ligne comme une ligne dans un document, lisez la ligne suivante, effectuez vos opérations, puis faites avancer le curseur.