PDA

Ver la Versión Completa : Funcion IN en Procedimiento Almacenado


mjjj
02-10-2012, 23:18:55
Estimados, estoy intentando crear un procedimiento con una variable de entrada que sea de tipo varchar, tal que esta varible haga referencia a al identificador que deseo buscar.
Creo que lo mejor es un ejemplo, solo muestro la parte donde tengo problema.


begin
for select id_item, nombre from insumos into :id_item, :nombre do
begin
select coalesce(avg(precio),0), coalesce(sum(cantidad),0) from inventario
where id_bodega in (:bodegas) and id_item =:id_item into :precio_ingreso, :cantidad_ingreso;
end
suspend
end


La variable de entradad la genero en Delphi según las necesidades del usuario, y puede ser por ejemplo (1), (2, 3), (1, 2, 3, 4).

el problema esta en que me arroja un error, ya que trata de convertir la cadena en integer, ya que el campo id_bodega es entero.

Si ejecuto esta sentencia como una consulta directamente no me arroja error, el problema está en que necesariamente debo ejecutarla dentro de un procedimiento almacenado.

Como puedo pasarle esta variable al procedimiento?

Casimiro Notevi
02-10-2012, 23:25:08
En principio... deberías poner el código completo del procedimiento, nos estamos perdiendo datos.

mjjj
03-10-2012, 00:33:15
lo que esta faltando es la declaracion de la varialbes de entrada y salida, las de salida están ok, la de entrada es donde tengo problema, ya que la he definido como varchar ya que quiero buscar en varias bodega, por esto la consulta en el procedimiento con la condición "IN". He aqui el problema, ya que el campo id_bodega de la tabla inventario es de tipo integer, sin embargo, yo intreso una cadena para que debe buscar en mas de una bodega... por ejemplo:

- (1)
- (1,3)
- (2,3,5)

Espero se entienda, y me puedan ayudar a resolverlo. Utilizo Firebird 2.5.

Casimiro Notevi
03-10-2012, 00:40:44
Dudo que eso funcione (no puedo asegurarlo al 100%), para lo que quieres es posible que tengas que usar execute_statement, haz una búsqueda, se ha tratado en diversas ocasiones.
Básicamente se trata de componer la sentencia completa y pasarla como una cadena, resumiendo:

sentencia := 'select * from tbtabla where id=5';
execute_statement( sentencia );

Lepe
03-10-2012, 09:26:08
Ojito que el predicado "in" es limitado. Le caben creo 1024 elementos o algo así, pero sigue siendo limitado.

cloayza
03-10-2012, 15:00:45
Podría ser algo así...

FOR SELECT id_item, nombre
FROM insumos
INTO :id_item, :nombre
DO
BEGIN
EXECUTE STATEMENT ('SELECT coalesce(avg(precio),0), coalesce(sum(cantidad),0)
FROM inventario
WHERE id_bodega in (:bodegas) AND id_item =:id_item INTO recio_ingreso, :cantidad_ingreso')
(bodegas:=:Bodegas, id_item:=:Id_item);
suspend;
end


El parametro :Bodegas deberia ser enviado así '1,2,...', quedando la sentencia id_bodega in (1,2,3)

Espero te ayude, saludos cordiales

Casimiro Notevi
03-10-2012, 15:34:19
Seguro que no lo has probado porque eso no funciona.
Tienes que pasarle la cadena completa ya formada.
O sea, algo como lo que te he puesto en el ejemplo anterior, 'montas' la cadena en una variable y la llamas con execute_statement.

mjjj
03-10-2012, 15:46:03
gracias a todos por sus comentarios, finalmente el tema lo resolví asi.


begin
for select id_item, nombre from insumos
into :id_item, :nombre do
begin
execute statement
'select coalesce(avg(precio),0), coalesce(sum(cantidad),0) from inventario
where id_item ='||:id_item||' and id_bodega in '||(:bodegas)
into :precio_ingreso, :cantidad_ingreso;
suspend;
end
end


Esto funciona bien y rápido, sin embargo, como se comportará al tener muchos más registros?
El comando execute statement es igual de eficiente que una consulta directa?

Gracias nuevamente.

Casimiro Notevi
03-10-2012, 16:56:29
El comando execute statement es igual de eficiente que una consulta directa?
No, no es tan rápido, pero sólo lo notarás en consultas muy complejas con muchas tablas involucradas.