Position actuelle: Accueil> Derniers articles> Analyse des raisons pour lesquelles next_result () provoque une boucle morte lorsqu'elle est utilisée dans une boucle

Analyse des raisons pour lesquelles next_result () provoque une boucle morte lorsqu'elle est utilisée dans une boucle

gitbox 2025-04-29

Les développeurs utilisent souvent la fonction Next_Result () lors de l'utilisation de PHP pour les opérations de base de données, en particulier lors de l'utilisation de la fonction Multi-Result Set (Multi_Query) de MySQLI. Cependant, si elle est mal utilisée dans la boucle, elle peut déclencher, ce qui fait que le script ne se termine pas normalement. Cet article analysera les raisons de cette occurrence en détail et fournira une solution fiable.

1. Le problème réapparaît

Supposons que nous ayons un morceau de code qui utilise Multi_Query pour exécuter plusieurs instructions SQL:

 $mysqli = new mysqli("localhost", "user", "password", "database");

$sql = "
    SELECT * FROM users;
    SELECT * FROM orders;
    SELECT * FROM products;
";

if ($mysqli->multi_query($sql)) {
    do {
        if ($result = $mysqli->store_result()) {
            while ($row = $result->fetch_assoc()) {
                print_r($row);
            }
            $result->free();
        }
        // Voici la clé
    } while ($mysqli->next_result());
}

Dans ce code, nous voulons exécuter trois instructions de sélection dans la séquence et traiter leurs ensembles de résultats respectifs. Le but de next_result () est de préparer le prochain ensemble de résultats.

Le problème est: si la dernière fois que Next_Result () est appelée est vraie , mais Store_Result () renvoie FALSE (car il n'y a plus de jeux de résultats), il entrera dans une boucle morte.

2. Pourquoi y a-t-il un cercle vicieux?

Le but de next_result () est de déplacer Mysqli vers le jeu de résultats suivant et de renvoyer un booléen:

  • Le retour de vrai signifie qu'il y a plus d'ensembles de résultats ou un commutateur réussi;

  • Le renvoi de faux signifie qu'il n'y a plus de ensembles de résultats ou une erreur se produit.

Cependant, lorsque le dernier ensemble de résultats est un ensemble de résultats vide (comme la dernière instruction est sélectionné mais aucun résultat, ou une instruction non remerciale telle que la mise à jour ), Store_Result () renvoie false , mais next_result () peut toujours renvoyer vrai , provoquant DO ... tout en poursuivant l'exécution - il n'y a pas de condition de sortie, et la boucle morte se produit!

3. Solution

? Méthode 1: Vérifiez s'il y a plus d'ensembles de résultats

Vous pouvez utiliser la méthode More_Results () pour déterminer s'il existe toujours un ensemble de résultats qui peut être traité:

 $mysqli = new mysqli("localhost", "user", "password", "database");

$sql = "
    SELECT * FROM users;
    SELECT * FROM orders;
    UPDATE users SET status = 'active' WHERE id = 1;
";

if ($mysqli->multi_query($sql)) {
    do {
        if ($result = $mysqli->store_result()) {
            while ($row = $result->fetch_assoc()) {
                print_r($row);
            }
            $result->free();
        } else {
            // Pas un ensemble de résultats,peut être UPDATE、INSERT attendez
            if ($mysqli->errno) {
                echo "MySQL erreur:" . $mysqli->error;
            }
        }

    } while ($mysqli->more_results() && $mysqli->next_result());
}

? Méthode 2: Définissez le nombre maximum de cycles (défensif)

Si vous ne pouvez pas déterminer complètement le nombre d'ensembles de résultats, vous pouvez définir un nombre maximal de boucles pour empêcher les boucles mortes:

 $maxLoops = 10;
$loopCounter = 0;

if ($mysqli->multi_query($sql)) {
    do {
        if (++$loopCounter > $maxLoops) {
            echo "Une boucle morte possible a été détectée,Abandonner l'opération";
            break;
        }

        if ($result = $mysqli->store_result()) {
            while ($row = $result->fetch_assoc()) {
                print_r($row);
            }
            $result->free();
        }

    } while ($mysqli->next_result());
}

4. Résumé

Lorsque vous utilisez Next_Result () , vous devez accorder une attention particulière à la valeur de retour qui ne peut pas être entièrement fiable. Pour utiliser avec More_Results () , assurez-vous de continuer uniquement s'il y a en effet le jeu de résultats suivant. Sinon, il est facile de provoquer une boucle morte sous certains chemins d'exécution SQL, surtout lorsqu'il y a des ensembles de résultats vides ou une exécution mixte d'instructions non Quey.

Pour voir plus de meilleures pratiques sur les opérations de PHP et de base de données, vous pouvez visiter:

https://gitbox.net/php-mysql-best-practices