Mysql
 sql >> Base de données >  >> RDS >> Mysql

PDO "Exception non interceptée 'PDOException' .. Impossible d'exécuter des requêtes alors que d'autres requêtes non tamponnées sont actives. Envisagez d'utiliser PDOStatement::fetchAll(). »

Vous devez extraire jusqu'à ce qu'une tentative d'extraction de ligne échoue. Je sais que vous n'avez peut-être qu'une seule ligne dans le jeu de résultats et que vous pensez qu'une extraction suffit, mais ce n'est pas le cas (lorsque vous utilisez des requêtes sans tampon). PDO ne sait pas combien de lignes il y a jusqu'à ce qu'il atteigne la fin, où il essaie de récupérer la ligne suivante, mais il échoue.

Vous avez probablement d'autres déclarations où vous n'avez pas entièrement "récupéré jusqu'à ce qu'une récupération échoue". Oui, je vois que vous récupérez jusqu'à ce que la récupération échoue pour un des déclarations, mais cela ne signifie pas que vous l'avez fait pour toutes.

Pour clarifier -Lorsque vous exécutez une requête via execute(), vous créez un jeu de résultats qui doit être récupéré de la base de données dans php. PDO ne peut gérer qu'un seul de ces "ensembles de résultats en cours de récupération" à la fois (par connexion). Vous devez récupérer complètement le jeu de résultats, jusqu'à la fin, avant de pouvoir commencer à récupérer un jeu de résultats différent à partir d'un appel différent à execute().

Lorsque vous "appelez fetch() jusqu'à ce qu'un fetch() échoue", le fait que vous ayez atteint la fin des résultats est noté en interne par PDO lorsque cet appel final à fetch() échoue car il n'y a plus de résultats. PDO est alors convaincu que les résultats sont entièrement récupérés, et il peut nettoyer toutes les ressources internes entre php et la base de données qui ont été établies pour cet ensemble de résultats, vous permettant de faire/récupérer d'autres requêtes.

Il existe d'autres façons de faire en sorte que PDO "appelle fetch() jusqu'à ce qu'un fetch() échoue".

  1. Utilisez simplement fetchAll(), qui récupère simplement toutes les lignes, et ainsi il atteindra la fin du jeu de résultats.
  2. ou appelez simplement closeCursor()

* Si vous regardez la source de closeCursor(), l'implémentation par défaut récupère littéralement les lignes et les supprime jusqu'à ce qu'elle atteigne la fin. C'est écrit en c évidemment, mais ça fait plus ou moins ça :

function closeCursor() {
    while ($row = $stmt->fetch()) {}
    $this->stmtFullyFetched = true;
}

Certains pilotes db peuvent avoir une implémentation plus efficace qui ne les oblige pas à récupérer de nombreuses lignes dont personne ne se soucie, mais c'est la manière par défaut de PDO de le faire. Quoi qu'il en soit...

Normalement, vous n'avez pas ces problèmes lorsque vous utilisez des requêtes mises en mémoire tampon. La raison en est qu'avec les requêtes mises en mémoire tampon, juste après leur exécution, PDO récupère automatiquement les résultats de la base de données dans la mémoire php, il effectue donc automatiquement la partie "appel fetch() jusqu'à ce qu'un fetch() échoue". Lorsque vous appelez plus tard fetch() ou fetchAll() vous-même, il récupère les résultats de la mémoire php, pas de la base de données. Donc, fondamentalement, le jeu de résultats est immédiatement récupéré lors de l'utilisation de requêtes mises en mémoire tampon, il n'y a donc aucune possibilité d'avoir plus d'un "jeu de résultats en cours de récupération" en même temps (car php est monothread, donc aucune chance de 2 requêtes fonctionnant en même temps).

Étant donné ceci :

$sql = "select * from test.a limit 1";
$stmt = $dbh->prepare($sql);
$stmt->execute(array());

Façons de récupérer entièrement le jeu de résultats (en supposant que vous ne vouliez que la première ligne) :

$row = $stmt->fetch();
$stmt->closeCursor();

ou

list($row) = $stmt->fetchAll(); //tricky

ou

$row = $stmt->fetch();
while ($stmt->fetch()) {}