sql >> Base de Datos >  >> RDS >> Mysql

PDO “Excepción no detectada 'PDOException'... No se pueden ejecutar consultas mientras otras consultas sin búfer están activas. Considere usar PDOStatement::fetchAll().”

Debe buscar hasta que falle un intento de búsqueda de fila. Sé que es posible que solo tenga una fila en el conjunto de resultados y piense que una búsqueda es suficiente, pero no lo es (cuando usa consultas sin búfer). PDO no sabe cuántas filas hay hasta que llega al final, donde intenta obtener la siguiente fila, pero falla.

Probablemente tenga otras declaraciones en las que no haya "recuperado completamente hasta que falló una recuperación". Sí, veo que buscas hasta que falló la búsqueda para uno de las declaraciones, pero eso no significa que lo hayas hecho por todas ellas.

Para aclarar:cuando ejecuta una consulta a través de execute(), crea un conjunto de resultados que debe obtenerse de la base de datos en php. PDO solo puede manejar 1 de estos "conjuntos de resultados en curso de obtención" a la vez (por conexión). Debe obtener completamente el conjunto de resultados, hasta el final, antes de que pueda comenzar a obtener un conjunto de resultados diferente de una llamada diferente para ejecutar().

Cuando "llama a fetch() hasta que falle fetch()", el hecho de que llegó al final de los resultados es notado internamente por PDO cuando la llamada final a fetch() falla debido a que no hay más resultados. Luego, PDO está satisfecho de que los resultados se hayan obtenido por completo y puede limpiar los recursos internos entre php y la base de datos que se establecieron para ese conjunto de resultados, lo que le permite realizar/obtener otras consultas.

Hay otras formas de hacer que PDO "llame a fetch() hasta que falle fetch()".

  1. Simplemente use fetchAll(), que simplemente obtiene todas las filas y llegará al final del conjunto de resultados.
  2. o simplemente llame a closeCursor()

*si observa la fuente de closeCursor(), la implementación predeterminada literalmente solo obtiene las filas y las descarta hasta que llega al final. Está escrito en c obviamente, pero más o menos hace esto:

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

Algunos controladores de db pueden tener una implementación más eficiente que no requiere que obtengan muchas filas que a nadie le importan, pero esa es la forma predeterminada en que lo hace PDO. De todos modos...

Normalmente, no tiene estos problemas cuando usa consultas almacenadas en búfer. La razón es que con las consultas almacenadas en búfer, justo después de ejecutarlas, PDO obtendrá automáticamente los resultados de la base de datos en la memoria php, por lo que hace la parte de "llamar a buscar () hasta que falle una búsqueda ()" por usted, automáticamente. Cuando luego llama a fetch() o fetchAll() usted mismo, está obteniendo resultados de la memoria php, no de la base de datos. Entonces, básicamente, el conjunto de resultados se recupera completamente de inmediato cuando se usan consultas almacenadas en búfer, por lo que no hay oportunidad de tener más de 1 "conjunto de resultados en proceso de recuperación" al mismo tiempo (porque php tiene un solo subproceso, por lo que no hay posibilidad de 2 consultas ejecutándose al mismo tiempo).

Dado esto:

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

Formas de obtener completamente el conjunto de resultados (suponiendo que solo desea la primera fila):

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

o

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

o

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