Ver Mensaje Individual
  #4 (permalink)  
Antiguo 04/08/2014, 06:39
Avatar de gnzsoloyo
gnzsoloyo
Moderador criollo
 
Fecha de Ingreso: noviembre-2007
Ubicación: Actualmente en Buenos Aires (el enemigo ancestral)
Mensajes: 23.324
Antigüedad: 16 años, 5 meses
Puntos: 2658
Respuesta: error 1326 en fallos

@andres18281:
Este tema, y este mismo procedimiento, ya ha sido motivo de otro post (que deberías haber continuado y no abriur uno nuevo), y en ese momento te hice algunas observaciones que por lo visto no has tenido mínimamente en cuenta...

Por lo pronto te hice la observación de que estás haciendo jOINs implícitos, pero no estás poniendo las condiciones de JOIN en el WHERE, por lo que existe riesgo potencial de que se generen productos cartesianos.
Por otro lado, ya te había dicho que yo veía innecesario el uso de cursores para recorrer el resultado de un join, cuyo origen era el resultado de otra consulta, simplemente para hacer inserciones. un JOIN más complejo es suficiente para el caso.
Además, ya te había mencionado que tablas TEMPORARY son más prácticas para lo que necesitas hacer.

En resumen la idea es esta:

- En primera instancia, lo que intentas resolver es obtener todas aquellas facturas que están en un determinado período de tiempo. Eso lo haces con esto:
Código MySQL:
Ver original
  1. SELECT fact_cod_fac, fact_fecha
  2. FROM Factura
  3. WHERE fact_fecha >= fecha_inicio AND fact_fecha <= fecha_final;
Yo aquí noto que podrías usar un BETWEEN para simplificar, pero eso es algo formal.
De esta consulta salen dos datos: Factura y fecha, y esos datos luego los recorres sólo para hacer eso:
Código MySQL:
Ver original
  1. SELECT ord_cod_zap,pro_nomb,cal_cost,pro_nit
  2. FROM ord_compra oc, Producto p, Calzado c
  3. WHERE ord_cod_fact = codigo_factura;
Esta segunda query tiene un problema: No se ve que haya una relación entre las tres tablas, o al menso no se está indicando.
Cuando MySQL se encuentra con eso, realiza una junta natural emparejando, implicitamente, aquellos campos que entre dos tablas tengan el mismo nombre. Esto puede tener efectos extraños si dos tablas tienen un campo llamado "id", "nombre", "fecha" o cualquier otro con identica denominación, sin importar si representan lo mismo.
¿Se entiende el riesgo?
Además, como de todos modos el filtro se aplica luego de realizar el JOIN implícito, estás haciendo un full table scan, que es una de las peores formas de consulta existentes, luego del producto cartesiano. Es muchísimo más eficiente usar JOIN explícitos, ya que estos sólo leen aquellos registros que coinciden entre tablas (especialmente cuando hay FKs definidas).

Bien, vamos a suponer que las tablas tienen bien distinguidos los nombres de sus campos, y que no se repiten entre tablas más que los nombres de las claves primarias y su respectiva referencia de clave foránea.
En ese contexto, la sintaxis debería ser:
Código MySQL:
Ver original
  1. SELECT ord_cod_zap,pro_nomb,cal_cost,pro_nit
  2. FROM ord_compra oc
  3.     INNER JOIN Producto p ON oc.pro_id = p.pro_id
  4.     INNER JOIN Calzado c ON p.pro_id = c.pro_id

Ahora bien, siendo que la query anterior devuelve fecha y numero de factura, y que lo que pareces querer es la fecha, para cada orden producto (calzado) vendido, las dos consultas bien podrían combinarse en una sola:
Código MySQL:
Ver original
  1. SELECT fact_fecha, ord_cod_zap, pro_nomb, cal_cost, pro_nit
  2. FROM Factura F
  3.     INNER JOIN ord_compra oc ON f.fact_cod_fac = oc.ord_cod_fact
  4.     INNER JOIN Producto p ON oc.pro_id = p.pro_id
  5.     INNER JOIN Calzado c ON p.pro_id = c.pro_id
  6. WHERE f.fact_fecha BETWEEN fecha_inicio AND fecha_final;
En ese contexto, una sola consulta estaría devolviendo todo lo que buscas, y con precisión.

- Por otro lado, planteas que quieres una tabla temporal donde insertar esos datos, pero usas una tabla MEMORY para eso.
te comento que las tablas MEMORY son tablas de estructura persistente, pero contenido volatil, por lo que luego de ejecutarse el proceso es probable que se enceuntre vacía. O al menos que se vacíe de datos al cerrarse la conexión que la usa.
Eso es así por feinición de la tabla.
Si lo que necesitas es una tabla, para luego consultarla en el acto, y que desaparezca, no necesitas una MEMORY, sino una TEMPORARY. Esta existe sólo durante la ejecucion del proceso, y se borra inmediatamente cuando termina.
Ahora bien, si no vas a matener persistencia del reporte, lo que te conviene es crear una temporary y usar el mismo SP para que devuelva la tabla resultado antes de que est desaparezca, o simplemente usar todo el SP para que ejecute la consulta.
Tu decides...

Yo, personalmente, intentaría algo parecido a esto:

Código MySQL:
Ver original
  1. CREATE PROCEDURE devuelve_informe_venta(IN fecha_inicio DATE, IN fecha_final DATE)
  2.     SET @id = 0;
  3.     CREATE TEMPORARY TABLE tablareporte AS
  4.     SELECT (@id:=@id+1)idreporte, fact_fecha, ord_cod_zap, pro_nomb, cal_cost, pro_nit
  5.     FROM Factura F
  6.         INNER JOIN ord_compra oc ON f.fact_cod_fac = oc.ord_cod_fact
  7.         INNER JOIN Producto p ON oc.pro_id = p.pro_id
  8.         INNER JOIN Calzado c ON p.pro_id = c.pro_id
  9.     WHERE f.fact_fecha BETWEEN fecha_inicio AND fecha_final;
  10.     SELECT *
  11.     FROM tablareporte;
  12.  END;
o bien simplemente:
Código MySQL:
Ver original
  1. CREATE PROCEDURE devuelve_informe_venta(IN fecha_inicio DATE, IN fecha_final DATE)
  2.     SET @id = 0;
  3.     SELECT (@id:=@id+1)idreporte, fact_fecha, ord_cod_zap, pro_nomb, cal_cost, pro_nit
  4.     FROM Factura F
  5.         INNER JOIN ord_compra oc ON f.fact_cod_fac = oc.ord_cod_fact
  6.         INNER JOIN Producto p ON oc.pro_id = p.pro_id
  7.         INNER JOIN Calzado c ON p.pro_id = c.pro_id
  8.     WHERE f.fact_fecha BETWEEN fecha_inicio AND fecha_final;
  9.  END;

Por supuesto, como ya te dije, estoy suponiendo las relaciones entre tus tablas, porque no las has explictado.
Pero yo haría algo así.

De hecho, casi todas las ocasiones donde he usado inicialmente cursores, termino utilizando tablas temporary, porque los cursores son ineficientes.

Com onota final, observo que en las condiciones de al menos uno de los IFs estás saliendo del LOOP antes de cerrar el cursor, por lo que el CLOSE al cursor jamás se ejecuta en esa instancia...
TEn cuidado con la lógica de ejecución.
__________________
¿A quién le enseñan sus aciertos?, si yo aprendo de mis errores constantemente...
"El problema es la interfase silla-teclado." (Gillermo Luque)