2009-05-08 33 views
14

Estoy tratando de entrar en detalles de PDO. Así codifiqué esto:PDO consultas sin búfer

$cn = getConnection(); 

// get table sequence 
$comando = "call p_generate_seq('bitacora')"; 
$id = getValue($cn, $comando); 

//$comando = 'INSERT INTO dsa_bitacora (id, estado, fch_creacion) VALUES (?, ?, ?)'; 
$comando = 'INSERT INTO dsa_bitacora (id, estado, fch_creacion) VALUES (:id, :estado, :fch_creacion)'; 
$parametros = array (
    ':id'=> (int)$id, 
    ':estado'=>1, 
    ':fch_creacion'=>date('Y-m-d H:i:s') 
); 
execWithParameters($cn, $comando, $parametros); 

mi función getValue funciona bien, y me da la siguiente secuencia para la mesa. Pero cuando me meto en execWithParameters, me sale esta excepción:

PDOException: SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute. in D:\Servidor\xampp_1_7_1\htdocs\bitacora\func_db.php on line 77

traté de modificar los atributos de conexión, pero no funciona.

Estos son mis funciones básicas db:

function getConnection() { 
    try { 
     $cn = new PDO("mysql:host=$host;dbname=$bd", $usuario, $clave, array(
       PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, 
      )); 

     $cn->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true); 
     return $cn; 
    } catch (PDOException $e) { 
     print "Error!: " . $e->getMessage() . "<br/>"; 
     die(); 
    } 
} 
function getValue($cn, $comando) { 
    $resul = $cn->query($comando); 
     if (!$resul) return null; 
     while($res = $resul->fetch()) { 
      $retorno = $res[0][0]; 
      break; 
     } 
     return $retorno; 
} 
function execWithParameters($cn, $comando, $parametros) { 
    $q = $cn->prepare($comando); 
    $q->execute($parametros); 
    if ($q->errorInfo() != null) { 
     $e = $q->errorInfo(); 
     echo $e[0].':'.$e[1].':'.$e[2]; 
    } 
} 

Alguien que puede arrojar una luz para esto? PD. Por favor, no sugiera hacer una identificación autónoma, porque estoy transfiriendo desde otro sistema.

+0

¿Cuál es la definición de p_generate_seq? MOSTRAR PROCEDIMIENTO p_generate_seq – VolkerK

+0

el problema no está allí, el mismo error ocurre con SELECT MAX (id) FROM dsa_bitacora –

Respuesta

21

El problema es que mysql solo permite un cursor destacado en un momento dado. Al usar el método fetch() y no consumir todos los datos pendientes, está dejando un cursor abierto.

El enfoque recomendado es consumir todos los datos utilizando el método fetchAll(). Una alternativa es usar el método closeCursor().

Si cambia esta función, creo que será más feliz:

<?php 
function getValue($cn, $comando) { 
    $resul = $cn->query($comando); 
    if (!$resul) return null; 
    foreach ($resul->fetchAll() as $res) { 
      $retorno = $res[0]; 
      break; 
    } 
    return $retorno; 
} 
?> 
+0

Sé usar funciones de conexión como las anteriores, pero tengo el mismo problema. El método fetchALL() no parece funcionar correctamente en mi máquina. ¿Algún consejo o alternativa desde tu respuesta? – JM4

8

El problema parece ser --- no estoy muy familiarizado con PDO --- que después de que su llamada a getValue regrese, la consulta todavía está vinculada a la conexión (Usted solo pide el primer valor, pero el la conexión devuelve varios, o espera hacerlo).

Quizás getValue se puede fijar mediante la adición de

$resul->closeCursor(); 

antes del retorno.

De lo contrario, si las consultas a getValue siempre devolverán un valor único (o suficiente), parece que se preferirá usar fetchAll.

+0

tx ... Acabo de probar el closeCursor y el fetchAll, y sigue planteando la misma excepción. –

0

Un amigo mío tenía el mismo problema con la compilación de xampp 1.7.1. Después de reemplazar xampp/php/* por la versión 5.2.9-2 de php.net y copiar todos los archivos necesarios en xampp/apache/bin funcionó bien.

0

Si está usando XAMPP 1.7.1, sólo tiene que actualizar a 1.7.2.

16

No creo que PDOStatement :: closeCursor() funcione si no está haciendo una consulta que devuelve datos (es decir, una ACTUALIZACIÓN, INSERCIÓN, etc.).

Una mejor solución es simplemente unset() el objeto PDOStatement después de llamar a PDOStatement :: execute():

$stmt = $pdo->prepare('UPDATE users SET active = 1'); 
$stmt->execute(); 
unset($stmt); 
+0

tengo que comprobar esto, gracias –

+0

Tenía el mismo problema en una función recursiva php. Gracias por este problema de respuesta resuelto de esta manera: $ rows = $ sth-> fetchAll (PDO :: FETCH_ASSOC); \t \t \t unset ($ sth); \t \t \t foreach ($ rows as $ row). Lo que tenía antes: while ($ row = $ sth-> fetch (PDO :: FETCH_ASSOC)). ¡Gracias! – Alqin

2

Me acabo de pasar 15 minutos buscando en Google en todo el Internet, y por lo menos visitan 5 diferentes Stackoverflow preguntas, algunos que afirmaron que mi error aparentemente surgió de la versión incorrecta de PHP, la versión incorrecta de la biblioteca MySQL o cualquier otra cosa mágica de la caja negra ...

Cambié todo mi código al usar "fetchAll" e incluso llamé closeCursor() y unset() en el objeto de consulta después de cada consulta. ¡Honestamente estaba desesperado! También probé el indicador MYSQL_ATTR_USE_BUFFERED_QUERY, pero no funcionó.

FINALMENTE Tiré todo por la ventana y miré el error PHP, y rastreé la línea de código donde sucedió.

SELECT AVG((original_bytes-new_bytes)/original_bytes) as saving 
    FROM (SELECT original_bytes, new_bytes FROM jobs ORDER BY id DESC LIMIT 100) AS t1 

De todos modos, el problema ocurrió porque mis original_bytes y new_bytes tanto en bigints sin firmar, y eso significaba que si alguna vez tenía un trabajo donde los new_bytes donde en realidad más grande que el original_bytes, entonces habría un desagradable error "fuera de rango" de MySQL. Y eso sucedió al azar después de ejecutar mi servicio de minificación por un tiempo.

¿Por qué diablos tengo este raro error de MySQL en lugar de simplemente darme el error simple, me supera? De hecho, apareció en SQLBuddy (peso ligero PHPMyAdmin) cuando ejecuté la consulta sin formato. Tenía excepciones PDO activadas, por lo que debería haberme dado el error de MySQL.

No importa, la conclusión es:

Si alguna vez tienes este error, asegúrese de comprobar que su prima MySQL es realmente correcto y sigue trabajando !!!

+1

Acabo de enfrentarme a este error críptico e inútil, y gracias a esa respuesta, pensé fuera de la caja por un momento. 'SHOW WARNINGS' en la misma conexión en la que falló la consulta resultó crucial para depurar eso. En mi caso, el error fue: 'Zona horaria desconocida o incorrecta: 'Europa/Londres'' que definí al crear la instancia PDO. Gracias @Henrik. –

Cuestiones relacionadas