Foros del Web » Programación para mayores de 30 ;) » Bases de Datos General » Mysql »

procedimiento no puede devolver un conjunto de resultados en el contexto dado

Estas en el tema de procedimiento no puede devolver un conjunto de resultados en el contexto dado en el foro de Mysql en Foros del Web. Hola nuevamente, tengo el siguiente procedimiento almacenado: Código: CREATE DEFINER=`root`@`localhost` PROCEDURE `PA_Venta`(xIdcliente INT, xIdempleados varchar(3), xIdproducto varchar(6), xcantidad Numeric(18,2), xPrecioUnit Numeric (18,2),xId_color int) BEGIN declare ...
  #1 (permalink)  
Antiguo 04/01/2010, 13:25
Avatar de Copia  
Fecha de Ingreso: noviembre-2009
Mensajes: 309
Antigüedad: 15 años
Puntos: 4
procedimiento no puede devolver un conjunto de resultados en el contexto dado

Hola nuevamente, tengo el siguiente procedimiento almacenado:
Código:
CREATE DEFINER=`root`@`localhost` PROCEDURE `PA_Venta`(xIdcliente INT, xIdempleados varchar(3),
                         xIdproducto varchar(6), xcantidad Numeric(18,2),
                         xPrecioUnit Numeric (18,2),xId_color int)
BEGIN
        declare idVenta int;  /* idventas tomara el ultimo valor auto*/
        Insert into ventas(fecha,Idcliente,Idempleados,Idproducto,cantidad,PrecioUnit,total,Id_color)
        values(current_date(),xIdcliente,xIdempleados,xIdproducto,xcantidad,xPrecioUnit,xcantidad*xPrecioUnit,xId_color);

        /* Ahora restando el stock*/

        update producto set stock = (stock - xcantidad)
        where xIdProducto = Idproducto;

        /* Mostrando el Resumen de venta */

        set idVenta = (SELECT LAST_INSERT_ID()
                      FROM ventas limit 1);  /*capturando el ultimo valor de
                      autoincrement*/

        Select v.Idventas, v.Fecha, c.nombre,e.nombre, p.Descripcion,v.Cantidad,
               v.PrecioUnit,v.total,co.Descripcion
               from ventas v,empleados e, clientes c, producto p, color co
	       where (v.Idventas = idVenta) AND  (c.Idcliente = v.Idcliente)
                     and (v.Idempleados = e.Idempleados) and (p.Idproducto = v.Idproducto)
                     and (v.Id_color = co.Id_color );

END
El cual es llamado desde php en la siguiente forma:
Código:
$resultado = mysql_query("call PA_Venta('$xIdcliente','$xIdempleados', '$xIdproducto', '$xcantidad', '$xPrecioUnit', 											 '$xId_color')") or die(mysql_error());
	  if ($row = mysql_fetch_array($resultado)){
/*	     var_dump($row, $resultado);*/
		 echo "<table border = '1'>\n";
		 echo "<tr><td>Numero de Venta</td><td>Fecha</td><td>Cliente</td><td>Empleado</td><td>Producto</td><td>Cantidad</td><td>Precio
		 Unitario</td><td>Total</td><td>Color</td></tr> \n";
		  do {
			  echo "<tr><td>".$row['Idventas']."</td><td>".$row['fecha']."</td><td>".$row[2]."</td><td>".$row[3]."</td><td>".$row[4]."
			  </td><td>".$row[5]."</td><td>".$row[6]."</td><td>".$row[7]."</td><td>".$row[8]."</td></tr>
			  \n";
			  } while ($row = mysql_fetch_array($resultado)); /* aca padeci como nunca por no darme cuenta que es mysql_fetch_array.*/
		 echo "</table>\n";
	 } else { echo "¡No se ha encontrado ningún registro!";}
y me vota el siguiente error:
PROCEDURE tienda.PA_Venta can't return a result set in the given context

Ahora, el error al parecer es en el procedimiento almacenado por ese motivo lo puse aca el post.

La verdad no se porque no me funcion, hize la mismo consulta desde php en el mismo php y funciona.
  #2 (permalink)  
Antiguo 04/01/2010, 13:48
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 17 años
Puntos: 2658
Respuesta: procedimiento no puede devolver un conjunto de resultados en el contexto d

Normalmente ese mensaje dice que se está intentando usar indebidamente una función o una sentencia en un contexto en que no trabaja.
En tu caso yo sospecho que es por el LAST_INSERT_ID(), que no se usa ni devuelve el dato que pides de la forma que lo pones.
LAST_INSERT_ID() devuelve el ultimo ID autonumérico insertado o modificado si luego no se ha realizado ninguna otra inserción o modificación. En tu caso lo estás poniendo luego de un UPDATE, lo que haría que te devolviese el ID del producto, y no de la venta.
Además, lo estás poniendo incorrectamente, por cuanto no devuelve un valor relacionado con ninguna tabla determinable, devuelve el último ID insertado o modificado, sea cual sea la tabla que se manipuló. No existe una relación entre la función y la tabla.

Yo te propondría esta sintaxis:
Código MySQL:
Ver original
  1. CREATE PROCEDURE `PA_Venta`
  2.   (xIdcliente INT,
  3.   xIdempleados varchar(3),
  4.   xIdproducto varchar(6),
  5.   xcantidad Numeric(18,2),
  6.   xPrecioUnit Numeric (18,2),
  7.   xId_color int)
  8.   DECLARE idVenta INT;  /* idventas tomara el ultimo valor auto*/
  9.   INSERT INTO ventas(fecha,Idcliente,Idempleados,Idproducto,cantidad,PrecioUnit,total,Id_color)
  10.   VALUES(current_date(), xIdcliente, xIdempleados, xIdproducto, xcantidad, xPrecioUnit, xcantidad*xPrecioUnit, xId_color);
  11.   /* Ahora restando el stock*/
  12.  
  13.   SET idVenta = SELECT LAST_INSERT_ID();  /*capturando el ultimo valor de autoincrement*/
  14.   UPDATE producto SET stock = (stock - xcantidad)
  15.   WHERE xIdProducto = Idproducto;
  16.  
  17.         /* Mostrando el Resumen de venta */
  18.     v.Idventas,
  19.     v.Fecha,
  20.     c.nombre,
  21.     e.nombre,
  22.     p.Descripcion,
  23.     v.Cantidad,
  24.     v.PrecioUnit,
  25.     v.total,
  26.     co.Descripcion
  27.   FROM ventas v
  28.     INNER JOIN empleados e ON (v.Idempleados = e.Idempleados)
  29.     INNER JOIN clientes c ON (c.Idcliente = v.Idcliente)
  30.     INNER JOIN producto p ON (p.Idproducto = v.Idproducto)
  31.     INNER JOIN color co ON (v.Id_color = co.Id_color )
  32.       WHERE v.Idventas = idVenta;

Además de lo dicho, el tipo de relaciones entre tablas no se debe hacer en el WHERE, por cuestiones de eficiencia, sino con JOIN. Si no te resulta así, prueba poner LEFT JOIN.
Atención: Sólo devolverá datos si se se cumplen todas las condiciones del JOIN.

Por el uso de LAST_INSERT_ID(): 12.9.3. Funciones de información

Respecto al mensaje de error: 19.2.1. CREATE PROCEDURE y CREATE FUNCTION (Ver nota)
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #3 (permalink)  
Antiguo 04/01/2010, 14:11
Avatar de Copia  
Fecha de Ingreso: noviembre-2009
Mensajes: 309
Antigüedad: 15 años
Puntos: 4
Respuesta: procedimiento no puede devolver un conjunto de resultados en el contexto d

vaya entonces por lo que me dices, es mejor hacer una consulta que vaya directo al ultimo valor de idventas...

Sorry con los joins no los uso porque no termino de comprenderlos.

Edito: ya hize las modificaciones:

Código:
CREATE DEFINER=`root`@`localhost` PROCEDURE `PA_Venta`(xIdcliente INT, xIdempleados varchar(3),
                         xIdproducto varchar(6), xcantidad Numeric(18,2),
                         xPrecioUnit Numeric (18,2),xId_color int)
BEGIN

  DECLARE idVenta INT;  /* idventas tomara el ultimo valor auto*/
  INSERT INTO ventas(fecha,Idcliente,Idempleados,Idproducto,cantidad,PrecioUnit,total,Id_color)
  VALUES(CURRENT_DATE(), xIdcliente, xIdempleados, xIdproducto, xcantidad, xPrecioUnit, xcantidad*xPrecioUnit, xId_color);


  SET idVenta = (Select Idventas from ventas order by Idventas desc limit 1);  /*capturando el ultimo valor de autoincrement*/

  /* Ahora restando el stock*/

  UPDATE producto SET stock = (stock - xcantidad)
  WHERE xIdProducto = Idproducto;

        /* Mostrando el Resumen de venta */
  SELECT
    v.Idventas,
    v.Fecha,
    c.nombre,
    e.nombre,
    p.Descripcion,
    v.Cantidad,
    v.PrecioUnit,
    v.total,
    co.Descripcion
  FROM ventas v
    INNER JOIN empleados e ON (v.Idempleados = e.Idempleados)
    INNER JOIN clientes c ON (c.Idcliente = v.Idcliente)
    INNER JOIN producto p ON (p.Idproducto = v.Idproducto)
    INNER JOIN color co ON (v.Id_color = co.Id_color )
    WHERE v.Idventas = idVenta;
END
y lo probe en el mysql browser, y funciona, ahora por php sigue dando error.

Última edición por Copia; 04/01/2010 a las 14:18
  #4 (permalink)  
Antiguo 04/01/2010, 17:04
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 17 años
Puntos: 2658
Respuesta: procedimiento no puede devolver un conjunto de resultados en el contexto d

¿Para qué haces esto:
Código MySQL:
Ver original
  1. SET idVenta = (Select Idventas from ventas order by Idventas desc limit 1);
Si esto es el método correcto, tal como te lo puse:
Código MySQL:
Ver original
  1. SET idVenta = LAST_INSERT_ID();
En todo caso, cuando SELECT contra una variable la sintaxis correcta sería:
Código MySQL:
Ver original
  1. Select MAX(Idventas) INTO idVenta FROM ventas ;
Por lo que noto que no leíste la nota que te remarqué, y que dice:
Cita:
Los comandos que retornan un conjunto de resultados no pueden usarse desde una función almacenada. Esto incluye comandos SELECT que no usan INTO para tratar valores de columnas en variables
Respecto a los JOIN, es primordial que los comprendas, porque con ellos se desarrolla la inmensa mayoría de las consultas que se usan.
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)
  #5 (permalink)  
Antiguo 04/01/2010, 23:20
Avatar de Copia  
Fecha de Ingreso: noviembre-2009
Mensajes: 309
Antigüedad: 15 años
Puntos: 4
Respuesta: procedimiento no puede devolver un conjunto de resultados en el contexto d

Bueno no entiendo mucho, lo que crei entender era que el problema a cual se debia el error era por LAST_INSERT_ID() porque toma el ultimo valor de una tabla autoincrement, sin distinguir entre ellas, entonces suponiendo que si tengo dos tablas autoincrement y una es mas baja que la otra y quiero el valor de la mas baja, no me conbiene. Por eso hize esta consulta que hace li mismo:

SET idVenta = (SELECT Idventas FROM ventas ORDER BY Idventas desc LIMIT 1);

y a la que me pone usted, no lo habia pensado.

Bien en cuanto a la sita no entiendo muy bien, porque si yo llamo a la misma funcion tal cual la tengo desde el query browser de mysql me funciona a la perfeccion, el problema radica al llamarlo desde php.

y no entiendo mas cuando dice esto: Esto incluye comandos SELECT que no usan INTO hasta ahora no e usado select con un into dentro. ¿A que se refiere?
  #6 (permalink)  
Antiguo 05/01/2010, 05:45
Avatar de gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 17 años
Puntos: 2658
Respuesta: procedimiento no puede devolver un conjunto de resultados en el contexto d

Cita:
Bueno no entiendo mucho, lo que crei entender era que el problema a cual se debia el error era por LAST_INSERT_ID() porque toma el ultimo valor de una tabla autoincrement, sin distinguir entre ellas, entonces suponiendo que si tengo dos tablas autoincrement y una es mas baja que la otra y quiero el valor de la mas baja, no me conbiene. Por eso hize esta consulta que hace li mismo:

SET idVenta = (SELECT Idventas FROM ventas ORDER BY Idventas desc LIMIT 1);-
En esto hay que atenerse a lo que los manuales explican: LAST_ISERT_ID() Devuelve el ID autoincremental que se ingresó en la última sentencia de inserción. Si se trató de de una inserción múltiple, sólo devuelve el valor de la primera inserción y no la última.
Se trata de una función muy eficiente, y que es mucho mejor que el ejemplo que das, porque en tu ejemplo, para encontrar ese valor debe leerse toda la tabla y ordenarse en forma decreciente . Te comento que el ordenamiento es una de las operaciones de mayor consumo de recursos en una base de datos, luego de los productos cartesianos.
Además, piénsalo así: ¿Para qué hacer una lectura de tabla, si una función me devuelve el valor buscado?
Lo que debes recordar es que ese valor no es permanente: Cambia con la siguiente inserción, por lo que la toma del dato debe ser inmediata a la ejecución (por eso la cambié de lugar).

Cita:
Bien en cuanto a la sita no entiendo muy bien, porque si yo llamo a la misma funcion tal cual la tengo desde el query browser de mysql me funciona a la perfeccion, el problema radica al llamarlo desde php.
Esto me parece que no lo habías mencionado, y es el corazón de tu problema.
Te has encontrado con un BUG de PHP (ver: Bug #42548. PROCEDURE xxx can't return a result set in the given context (works in 5.2.3!!))
Aparentemente podría resolverse usando PHP 5.2.3, o cualquier versión de PHP posterior al 01/01/2008.
El problema se originaría porque un SP que retorne un set (tabla) es tomado por PHP como un multi_query, por lo que no puede ejecutarlo dada la configuración que el servidor de PHP tiene.
¿Solución? Saca el SELECT fuera del SP y ejecútalo con otra consulta a continuación (la simpleza por sobre todo).

Cita:
y no entiendo mas cuando dice esto: Esto incluye comandos SELECT que no usan INTO hasta ahora no e usado select con un into dentro. ¿A que se refiere?
A que la forma eficiente y estandarizada de poner valores obtenidos en un select dentro de variables es usando la cláusula INTO, tal y como te lo puse en el ejemplo:
Código MySQL:
Ver original
  1. SELECT MAX(Idventas) INTO idVenta FROM ventas ;

Tip final: El uso de una función MAX() es más eficiente que lo que haces tu, pero menos que usar simplemente LAST_INSERT_ID().
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)

Última edición por gnzsoloyo; 05/01/2010 a las 12:28
  #7 (permalink)  
Antiguo 05/01/2010, 09:08
Avatar de Copia  
Fecha de Ingreso: noviembre-2009
Mensajes: 309
Antigüedad: 15 años
Puntos: 4
Respuesta: procedimiento no puede devolver un conjunto de resultados en el contexto d

gracias gnzsoloyo por tomarte el tiempo y por responder como lo has hecho.

Ahora mismo estoy practicando con los inner para terminar de comprenderlo.

Saludos.

Etiquetas: conjunto, contexto, dado, devolver, procedimiento, resultados
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 11:43.