0

tengo una duda respecto al siguiente proceso.
Esto me ocurrió hace un tanto dentro de un código.

Estaba yo haciendo una simple query, que devuelve múltiples resultados.
Dentro de un código largo que corre día a día.

El código es algo como esto:

$query = "SELECT * FROM TABLA";
$respuesta = mysqli_query($conexion, $query);
if (mysqli_num_rows($respuesta) > 0) {
  while ($fila = mysqli_fetch_assoc($respuesta)) {
    [.....];
  }
}

Y solo por obtener un listado, lo cambié a lo sgte:

$query = "SELECT * FROM TABLA";
$respuesta = mysqli_query($conexion, $query);
if (mysqli_num_rows($respuesta) > 0) {
  while ($r= mysqli_fetch_assoc($respuesta)) {
    [.....];
  }
}
if (mysqli_num_rows($respuesta) > 0) {
  while ($fila = mysqli_fetch_assoc($respuesta)) {
    [.....];
  }
}

Por alguna razón, esta segunda forma, se corta luego del primer IF, y no ejecuta el segundo.
No se si es problema de mi código, o algo que no se puede hacer.

Excorpion
  • 4,240
  • 1
  • 8
  • 27
  • No ejecuta el segundo if, o entra en el segundo if pero no ejecuta el while? – Jakala May 24 '21 at 14:17
  • Aparte que el ejemplo mira el mysql_num_rows de $result, no de $respuesta – Jakala May 24 '21 at 14:18
  • No entra, y perdon, lo otro es error mio ahora. – Excorpion May 24 '21 at 14:24
  • `ǹum_rows` no es la mejor forma de saber si hay filas, porque entre otras cosas depende de la configuración del buffer. ¿Qué ocurre dentro del `while`? Si ahí llenas un array es mejor verificar luego ese array para saber si hay datos. Otra opción **segura** para saber si hay filas es verificar con un `SELECT COUNT(*)`... Sea como sea, no le veo ningún sentido a dos `if` para lo mismo. – A. Cedano May 24 '21 at 14:31
  • Pero a pesar de no tener sentido... causaría problemas el hacerlo de ese modo ?? Tanto como para que el segundo if no se ejecute ?? – Excorpion May 24 '21 at 14:34
  • 1
    Si aplicas `mysqli_fetch_assoc()` una segunda vez sobre el mismo objeto del primer `if` no tiene ningún sentido. **mysqli devuelve los datos como un recurso o puntero**, de modo que cuando los lees en el primer `while`, **en el segundo `while` no encontrarás nada, porque ya vaciaste el puntero en el primero**. No sé si me entiendes, ese segundo `while` no tiene sentido si `$respuesta` no es un nuevo objeto producto de una nueva consulta a la BD. – A. Cedano May 24 '21 at 14:42
  • Entiendo, no tenía entendido que este era vaciado luego de usarlo. Gracias !! – Excorpion May 24 '21 at 14:48
  • 1
    Ya, no eres el primero que piensa que se pueden leer los datos una y otra vez. No es así, los datos vienen en un puntero. [Lo he explicado aquí](https://es.stackoverflow.com/a/329587/29967) y en unas cuantas preguntas más si mal no recuerdo ([aquí otra respuesta donde lo explico](https://es.stackoverflow.com/a/303055/29967)). – A. Cedano May 24 '21 at 14:52
  • Uff dificil encontrar ese post de hace más de un año con un título tan vago... pero gracias por la corrección ;) – Excorpion May 24 '21 at 14:53
  • Lo interesante sería saber por qué quieres leer dos veces los mismos resultados ¿? – A. Cedano May 24 '21 at 14:55
  • Está en el post -> `Y solo por obtener un listado...` – Excorpion May 24 '21 at 15:00
  • ¿Y qué quiere decir *obtener un listado* en este contexto? Cada iteracción del primer `while` será una fila de resultados por lo dicho anteriormente. O sea, el primer `while` irá moviendo el puntero de resultados fila a fila y cuando esto ocurra no habrá más datos que leer en `$respuesta`. Por tanto, si quieres mostrar un listado, debes construirlo dentro del primer `while` o bien guardar los datos en una variable si quieres usarlos a posteriori en otro contexto. – A. Cedano May 24 '21 at 15:06
  • Si vas a necesitar por alguna razón, recorrer los resultados más de una vez en partes distintas del código, la primera vez que recorras todos los resultados, que sea para crearte un array con ellos y despues recorre el array en vez de el resultado mysqli. – Ibai A. May 24 '21 at 15:20

1 Answers1

2

Si por alguna razón necesitas recorrer los resultados nuevamente, puedes resetear el apuntador con mysqli_data_seek():

if (mysqli_num_rows($respuesta) > 0) {
  while ($r= mysqli_fetch_assoc($respuesta))  
     ...
}
mysqli_data_seek($respuesta,0); // Resetea a la posición inicial (0)
if (mysqli_num_rows($respuesta) > 0) {
  while ($fila = mysqli_fetch_assoc($respuesta))
    ...
}
Sal
  • 6,626
  • 1
  • 7
  • 17
  • ¿Qué podría justificar un reseteo del puntero en este caso si serian siempre los mismos datos? – A. Cedano May 25 '21 at 13:03
  • Desconociendo que hay dentro del `while`, concedo que hay algoritmos que no resuelves en un solo ciclo. Hay problemas que sin *Funciones de ventana* ó *Expresiones de Tabla Común* suelen resolverse con métodos mas costosos que reiniciar un apuntador. Pienso en: cálculos estadísticos, tabulación cruzada y casos complejos de presentación, que no deberíamos resolver en la capa de persistencia. En ocasiones, es mas barato mover un apuntador (que por cierto, no "se vacía") que multiplicar memoria, hacer procedimientos almacenados, o hacer código complejo difícil de leer/mantener. – Sal May 25 '21 at 15:17
  • Gracias por tu comentario, muy interesante e iluminador y gracias por corregir mi concepto de que el puntero se vacía. Lo tendré en cuenta para un futuro. – A. Cedano May 25 '21 at 15:49