7 de diciembre de 2011

Una manera distinta de armar un IN dinamico a partir de una lista de elementos

Esta es una situación que seguro les ha pasado muchas veces. Tienen un SP que recibe un parametro usado para filtrar sobre una tabla, digamos @status. Normalmente haríamos algo como esto:

SELECT *
  FROM tabla
 WHERE (@status IS NULL OR status = @status)

Eso nos permitiria filtrar por un status especifico o no filtrar por status, indicando el valor NULL. Pero luego nos topamos con una situación en la que necesitamos filtrar por DOS valores de status distintos, digamos, registros ACTIVOS y ANULADOS. Obviamente nuestra primera intención es hacer:

SELECT *
  FROM tabla
 WHERE (@status IS NULL OR status IN (@status))

lo cual no es una instrucción valida para SQL Server, sin importar lo logico que se vea. Normalmente la solución a esta situación pasa por la creación de una función que tome un VARCHAR con la lista de valores separados por coma y devuelva un TABLE con los valores ya separados, y luego usamos ese TABLE para hacer un FULL JOIN o un IN (SELECT).

Pero hoy encontre una solución bien sencilla, usando las desconocidas (al menos para mi) capacidades XML de SQL Server. La idea, basicamente, es usar la lista de valores para crear un XML y luego usar ese XML como una fuente datos en un IN (SELECT). Aplicando esto al ejemplo que mencionaba al principio, la cosa quedaria asi:

DECLARE @x XML
SET @x = '' + REPLACE( @status, ',', '') + ''

SELECT *
  FROM tabla
 WHERE status IN (SELECT x.j.value('.', 'VARCHAR(max)') AS item FROM @x.nodes('//j') x(j))

Simple, cierto?

Victor Espina

No hay comentarios. :

Publicar un comentario