Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

PDO “Exceção não capturada 'PDOException' .. Não é possível executar consultas enquanto outras consultas sem buffer estiverem ativas. Considere usar PDOStatement::fetchAll().”


Você precisa buscar até que uma tentativa de busca de linha falhe. Eu sei que você pode ter apenas uma linha no conjunto de resultados e pensar que uma busca é suficiente, mas não é (quando você está usando consultas sem buffer). O PDO não sabe quantas linhas existem até chegar ao final, onde tenta buscar a próxima linha, mas falha.

Você provavelmente tem outras declarações em que você não "buscou até que uma busca falhou". Sim, vejo que você busca até que a busca falhou para um das declarações, mas isso não significa que você fez isso para todas elas.

Para esclarecer -Quando você executa uma consulta via execute(), você cria um conjunto de resultados que deve ser buscado do banco de dados no php. O PDO pode manipular apenas 1 desses "conjuntos de resultados em andamento de busca" de cada vez (por conexão). Você precisa buscar completamente o conjunto de resultados, até o final dele, antes de começar a buscar um conjunto de resultados diferente de uma chamada diferente para execute().

Quando você "chama fetch() até que um fetch() falhe", o fato de que você chegou ao final dos resultados é notado internamente pelo PDO quando essa chamada final para fetch() falha devido a não haver mais resultados. O PDO fica então convencido de que os resultados são totalmente obtidos e pode limpar quaisquer recursos internos entre o php e o db que foram estabelecidos para esse conjunto de resultados, permitindo que você faça/busque outras consultas.

Existem outras maneiras de fazer o PDO "chamar fetch() até que um fetch() falhe".
  1. Basta usar fetchAll(), que simplesmente busca todas as linhas e, portanto, atingirá o final do conjunto de resultados.
  2. ou apenas chame closeCursor()

*se você olhar para a fonte para closeCursor(), a implementação padrão literalmente apenas busca as linhas e as descarta até chegar ao final. Está escrito em c obviamente, mas mais ou menos faz isso:
function closeCursor() {
    while ($row = $stmt->fetch()) {}
    $this->stmtFullyFetched = true;
}

Alguns drivers de banco de dados podem ter uma implementação mais eficiente que não exige que eles busquem muitas linhas com as quais ninguém se importa, mas essa é a maneira padrão que o PDO faz. De qualquer forma...

Normalmente, você não tem esses problemas quando usa consultas em buffer. A razão é porque com consultas em buffer, logo após você executá-las, o PDO automaticamente buscará totalmente os resultados do db na memória php, então ele faz a parte "chamar fetch() até que um fetch() falhe" para você, automaticamente. Quando você chama fetch() ou fetchAll() mais tarde, está buscando resultados da memória php, não do banco de dados. Então, basicamente, o conjunto de resultados é imediatamente buscado totalmente ao usar consultas em buffer, então não há oportunidade de ter mais de 1 "conjunto de resultados em andamento para ser buscado" ao mesmo tempo (porque o php é de encadeamento único, portanto, não há chance de 2 consultas funcionando ao mesmo tempo).

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

Maneiras de buscar totalmente o conjunto de resultados (supondo que você queira apenas a primeira linha):
$row = $stmt->fetch();
$stmt->closeCursor();

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

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