Mysql
 sql >> Database >  >> RDS >> Mysql

PDO “Eccezione non rilevata 'PDOException' .. Impossibile eseguire query mentre altre query senza buffer sono attive. Prendi in considerazione l'utilizzo di PDOStatement::fetchAll()."

È necessario recuperare fino a quando un tentativo di recupero della riga non riesce. So che potresti avere solo una riga nel set di risultati e pensare che un recupero sia sufficiente, ma non lo è (quando utilizzi query senza buffer). PDO non sa quante righe ci sono finché non raggiunge la fine, dove prova a recuperare la riga successiva, ma fallisce.

Probabilmente hai altre dichiarazioni in cui non hai "recuperato fino a quando un recupero non è riuscito". Sì, vedo che recuperi fino a quando il recupero non è riuscito per uno delle affermazioni, ma ciò non significa che tu l'abbia fatto per tutte.

Per chiarire -Quando esegui una query tramite execute(), crei un set di risultati che deve essere recuperato dal db in php. PDO può gestire solo 1 di questi "set di risultati in corso di recupero" alla volta (per connessione). È necessario recuperare completamente il set di risultati, fino alla fine, prima di poter iniziare a recuperare un set di risultati diverso da una chiamata diversa da eseguire().

Quando "chiama fetch() fino a quando un fetch() fallisce", il fatto che hai raggiunto la fine dei risultati viene annotato internamente da PDO quando quella chiamata finale a fetch() fallisce perché non ci sono più risultati. PDO è quindi soddisfatto che i risultati siano stati completamente recuperati e può ripulire qualsiasi risorsa interna tra php e db stabilita per quel set di risultati, consentendoti di eseguire/recuperare altre query.

Ci sono altri modi per fare in modo che PDO "chiama fetch() fino a quando un fetch() fallisce".

  1. Usa semplicemente fetchAll(), che recupera semplicemente tutte le righe e quindi raggiungerà la fine del set di risultati.
  2. o semplicemente chiama closeCursor()

*se guardi il sorgente per closeCursor(), l'implementazione predefinita prende letteralmente semplicemente le righe e le scarta finché non raggiunge la fine. Ovviamente è scritto in c, ma più o meno fa così:

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

Alcuni driver db potrebbero avere un'implementazione più efficiente che non richiede loro di recuperare molte righe di cui nessuno si preoccupa, ma questo è il modo predefinito in cui PDO lo fa. Comunque...

Normalmente non si verificano questi problemi quando si utilizzano query memorizzate nel buffer. Il motivo è perché con le query bufferizzate, subito dopo averle eseguite, PDO recupererà automaticamente i risultati del db nella memoria php, quindi esegue automaticamente la parte "call fetch() fino a quando un fetch() fallisce" per te. Quando in seguito chiami tu stesso fetch() o fetchAll(), sta recuperando i risultati dalla memoria php, non dal db. Quindi, in pratica, il set di risultati viene immediatamente recuperato completamente quando si utilizzano query memorizzate nel buffer, quindi non c'è alcuna possibilità di avere più di 1 "set di risultati in corso di recupero" contemporaneamente (perché php è a thread singolo, quindi nessuna possibilità di 2 query in esecuzione allo stesso tempo).

Detto questo:

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

Modi per recuperare completamente il set di risultati (supponendo che tu voglia solo la prima riga):

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

o

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

o

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