Lo que sucede es que el store procedure es bastante complejo, es imposible reducirlo a solo un select:
Code: Select all
CREATE PROCEDURE `sp_descargalotecualquiera`(IN localid INT,IN articuloid INT,IN cuantas INT,IN modulo CHAR(4),IN operacion INT)
BEGIN
DECLARE loteslista varchar(300) DEFAULT "" ;
DECLARE descargas int DEFAULT 0 ;
DECLARE descargar int DEFAULT cuantas ;
DECLARE intentos int DEFAULT 0 ;
DECLARE rlocked int DEFAULT 0 ;
DECLARE finished int DEFAULT 0 ;
DECLARE lote_id char(20) ;
DECLARE lote_vc char(8) ;
DECLARE lote_un int ;
DECLARE arti_fr int ;
DECLARE arti_cs numeric(12,2) ;
DECLARE arti_lk tinyint ;
DECLARE arti_st int ;
DECLARE curLotes CURSOR FOR
SELECT stock_lote,stock_vence,stock_unids
FROM articulos_stocks
WHERE stock_local_id = localid AND stock_articulo_id = articuloid AND stock_unids > 0
ORDER BY stock_vence ;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET finished = 1 ;
lock_arti: loop
select articulo_fracciones,articulo_costo_promed,articulo_rlock INTO arti_fr,arti_cs,arti_lk
from articulos
where articulo_id = articuloid ;
if arti_lk = 0 then
update articulos set articulo_rlock = 1 where articulo_id = articuloid ;
set rlocked = 1 ;
leave lock_arti ;
end if ;
set intentos = intentos + 1 ;
if intentos > 5000 then
leave lock_arti ;
end if ;
end loop lock_arti ;
if rlocked = 1 then
OPEN curLotes ;
getLotes: LOOP
SELECT sum(stock_unids) as stock_total INTO arti_st
FROM articulos_stocks
WHERE stock_local_id = localid AND stock_articulo_id = articuloid AND stock_unids > 0 ;
FETCH curLotes INTO lote_id,lote_vc,lote_un ;
IF finished = 1 THEN
LEAVE getLotes ;
END IF;
IF lote_un >= descargar THEN
UPDATE articulos_stocks SET stock_unids = stock_unids - descargar WHERE stock_local_id = localid AND stock_articulo_id = articuloid AND stock_lote = lote_id ;
INSERT INTO kardex (kdx_local_id,kdx_arti_id,kdx_fecha,kdx_tipo,kdx_oper_mod,kdx_oper_id,kdx_arti_frac,kdx_stock_ant,kdx_stock_mov,kdx_stock_sld ,kdx_costo_prm,kdx_lote,kdx_vence)
VALUES( localid ,articuloid ,NOW() ,"-" ,modulo ,operacion ,arti_fr ,arti_st ,descargar ,arti_st-descargar,arti_cs ,lote_id ,lote_vc ) ;
SET descargas = descargas + descargar ;
SET loteslista = CONCAT( loteslista,"(",lote_id,",",lote_vc,",",descargar,")" );
ELSE
UPDATE articulos_stocks SET stock_unids = 0 WHERE stock_local_id = localid AND stock_articulo_id = articuloid AND stock_lote = lote_id ;
INSERT INTO kardex (kdx_local_id,kdx_arti_id,kdx_fecha,kdx_tipo,kdx_oper_mod,kdx_oper_id,kdx_arti_frac,kdx_stock_ant,kdx_stock_mov,kdx_stock_sld ,kdx_costo_prm,kdx_lote,kdx_vence)
VALUES( localid ,articuloid ,NOW() ,"-" ,modulo ,operacion ,arti_fr ,arti_st ,lote_un ,arti_st-lote_un ,arti_cs ,lote_id ,lote_vc ) ;
SET descargas = descargas + lote_un ;
SET loteslista = CONCAT( loteslista,"(",lote_id,",",lote_vc,",",lote_un,")" );
END IF ;
IF descargas = cuantas THEN
LEAVE getLotes ;
ELSE
SET descargar = descargar - descargas ;
END IF ;
END LOOP getLotes ;
CLOSE curLotes ;
end if ;
insert into descargas values(modulo,operacion,loteslista) ;
update articulos set articulo_rlock = 0 where articulo_id = articuloid ;
END
Así que como ven estoy usando la solución que me planteo Claudio Ricardo (crear una tabla en el lado de servidor que sirva de puente de resultados) y funciona perfecto.
Aprovechando el post, si se fijan en el inicio de la store procedure hago un lock a un registro, y he puesto 5000 intentos, alguien sabe si esta cantidad va bien o es muy bajo. Lo pregunto porque es un poco dificil testear concurrencia con un host remoto.
Cordiales saludos a todos.