viernes, 13 de enero de 2012

Pasando parámetros mutivalor de Reporting Services en procedimientos almacenados de MySQL

Configurar los parámetros con mútiples valores en SSRS no tiene mayor dificultad.
Se trata de elegir el parámetro que queremos pasar a multi valor, e indicarlo en un checkbox.

Lo que hace es pasar una lista de valores con los valores elegidos.
Si el acceso a datos lo hacemos a través de una consulta SQL, cambiaremos la consulta
“select * from usuarios where user_id=@PARAMETRO”
Por
“select * from usuarios where user_id in (@PARAMETRO)”


Hasta ahí, sencillo.
La complicación viene cuando lo que llamamos no es una consulta, sino un Procedimiento Almacenado. Y si el procedimiento Almacenado está en MySQL, las cosas se ponen más negras.


Parte 1: Modificaciones en el informe
Si tenemos un Procedimiento Almacenado con 3 parámetros (“A”,”B”,”C”), si el parámetro B viene con multiples valores, le pasará al procedimiento (“A”,”B1”,” B2”, “B3”, “C”), y dará error ya que el procedimiento espera 3 parámetros, no 5.

Lo que hay que hacer es al parámetro multivalor B es traducirlo a un único string separado por comas, es decir, pasar de “B1”,”B2”,”B3” a “B1,B2,B3”, con lo que los parámetros del procedimiento serían 3 (“A”,”B1,B2,B3”,C”)

Esto lo conseguimos configurando los parámetros de los conjuntos de datos,  y escribiendo una función personalizada




=JOIN(Parameters!Usuarios.Value,",")

Parte 2: Modificación en la base de datos


Sql Server nos habría facilitado la vida un montón ya que tenemos más recursos disponibles(funciones con retornos de tabla, funciones de cadena mucho más ricas, splits, etc...).

Con MySQL hay que dar bastante rodeo.


La única manera con la que he conseguido hacer funcionar esto ha sido a través de una tabla temporal, y con muchas pegas, ya que las tablas temporales no se pueden leer más de una vez. (Increible....)

Nos creamos un procedimiento almacenado en MySQL que nos meta en una tabla temporal los valores B1, B2, B3
CREATE DEFINER = 'root'@'%'
PROCEDURE _fn_StringCSVToTmpTable(texto VARCHAR(65535))
BEGIN
  declare pos int;
  declare elemento varchar(100);
  declare texto2 varchar(65535);

  DROP TEMPORARY TABLE IF EXISTS tmp_datos;
  CREATE TEMPORARY TABLE tmp_datos (campo1 INT NOT NULL) ENGINE = MEMORY;

  set pos=INSTR(texto,',');
  WHILE pos<>0 DO
    set elemento=substring(texto,1, pos-1);
    set texto2=substring(texto,pos+1);
    set texto=texto2; 
    insert into tmp_datos values (cast(trim(elemento) as unisgned));
    set pos=INSTR(texto,',');
  END WHILE;

  if texto<>"" then
    insert into tmp_datos values (cast(trim(elemento) as unisgned));
  end if;
END

Luego, este procedimiento almacenado es llamado desde el procedimiento principal.

CREATE DEFINER = 'root'@'%'
PROCEDURE PA2(IN p1 INT, IN texto varchar(200), IN p2 INT)
BEGIN
  call _fn_StringCSVToTmpTable(texto);
  select * from users where login in (select * from tmp_datos);
END

Cargamos la tabla temporal y hacemos la búsqueda.
Espero que os sea de utilidad.

2 comentarios:

Luis Enrique Hilario Esteban dijo...

estimados podrías dar mayor detalle, según tu explicación solo haces para mysql

Luis Enrique Hilario Esteban dijo...

Juan Manuel tengo 2 dataset uno con procedimiento almacenado hize lo que indicas poniendo un join pero no me devuelve los valores cuando selecciono