Generando múltiples filas de un string (split) en SQL Server
Las funciones sp_executesql y execute de t-sql nos permiten generar consultas dinámicamente concadenando textos, algo así se hace generalmente cuando se hace un "select in". Por ejemplo de marcas que tengan unos determinados productos, pero cuyo listado proviene de un conjunto de checks marcados desde una página web.
La consulta antes expuesta debería ser algo así;
select * from brands where brand_id in
(select brand_id from ProductsBrands where product_id in (12,13,14,77,121,598))
Ya que la parte de los identificadores de productos es variante muchos desarrolladores de t-sql optan por concadenar texto y ejecutar sus consultas con los comandos antes mencionados; este tipo de consultas no se pueden optimizar o mejorar mediante las statistics de SQL Server.
declare @listado nvarchar(1000)
set @listado = '10,11,12,13,14,15'
declare @sql nvarchar(1000)
set @sql = 'select * from brands where brand_id in (select brand_id from ProductsBrands where product_id in ( ' + @listado + ' ))'
EXEC(@sql)
Sin embargo existe una posibilidad de generar un conjunto de filas dado un string que contenga todos los identificadores de productos mediante la creación de una función definida por el usuario que devuelva una tabla (es decir un split de un string que devuelva un conjunto de filas con una columna que se pueda utilizar dentro de una "select in" sin necesidad de concadenar textos).
CREATE FUNCTION [dbo].[FnSplitTable]
(@Array varchar(1000),@separator char(1))
RETURNS @table_variable TABLE (col1 nvarchar(1000))
AS
BEGIN
declare @separator_position int
-- almacena el valor de cada vuelta
declare @array_value varchar(1000)
set @array = @array + @separator
-- recorre mientras haya un caracter separador
while patindex('%' + @separator + '%' , @array) <> 0
begin
-- se ubica el separador
set @separator_position = patindex('%' + @separator + '%' , @array)
-- se extrae el valor
set @array_value = substring(@array, 0, @separator_position)
-- se acorta la cadena de caracteres de busqueda
set @array = stuff(@array, 1, @separator_position, '')
-- se almacena en la tabla de respuesta
insert into @table_variable select @array_value as col1
end
RETURN
END
Finalmente nuestra consulta quedaría de la siguiente manera:
declare @listado nvarchar(1000)
set @listado = '10,11,12,13,14,15'
select * from brands
where brand_id in
(select brand_id from ProductsBrands where product_id in (
select col1 from dbo.FnSplitTable(@listado,',')))
Esta consulta si pasa por el proceso de las estadísticas y permite mejorar su rendimiento.
Enlaces relacionados
- The Curse and Blessings of Dynamic SQL
- Introduction to Dynamic SQL (Part 2)
- Parsing CSV Values Into Multiple Rows
- Converting Multiple Rows into a CSV String
- FIN -
5:22
|
Etiquetas:
multiple rows,
split,
sql server,
t-sql
|
This entry was posted on 5:22
and is filed under
multiple rows
,
split
,
sql server
,
t-sql
.
You can follow any responses to this entry through
the RSS 2.0 feed.
You can leave a response,
or trackback from your own site.
2 comentarios:
Excelente!... gracias...
Me podrian ayudar ya que quiero hacer de un estring que contiene los store procedure con sus respectivos parametro y retirarlos de dicho string para ejecutarlo... agradeceria su pronta ayuda.
Publicar un comentario