332 votos

¿Cómo dividir una cadena para que pueda acceder artículo x

Uso de SQL Server 2005, ¿cómo puedo dividir una cadena para que pueda acceder artículo X?

Por ejemplo, tomemos la cadena "Hola John Smith". ¿Cómo puedo dividir la cadena por un espacio y el acceso al elemento en el índice 1 que debe devolver "Juan"?

274voto

Nathan Bedford Puntos 3157

No creo que SQL Server tiene incorporada una función de división, por lo que no sea una UDF, la única respuesta que yo sé es secuestrar la PARSENAME función:

SELECT PARSENAME(REPLACE('Hello John Smith', ' ', '.'), 2) 

PARSENAME toma una cadena y lo divide en el plazo de caracteres. Se necesita un número como segundo argumento, y ese número se especifica a qué segmento de la cadena devolver (trabajar de atrás hacia delante).

SELECT PARSENAME(REPLACE('Hello John Smith', ' ', '.'), 3)  --return Hello

Obvio problema es cuando la cadena ya contiene un punto. Sigo pensando que el uso de una UDF es la mejor manera...alguna sugerencia?

136voto

Jonesinator Puntos 1793

Usted puede encontrar la solución en SQL definida por el usuario función para analizar una cadena delimitada útil (de El Proyecto de Código ).

U puede utilizar esta simple lógica -

 Declare @products varchar(200) = '1|20|3|343|44|6|8765'
Declare @individual varchar(20) = null

WHILE LEN(@products) > 0
BEGIN
    IF PATINDEX('%|%',@products) > 0
    BEGIN
        SET @individual = SUBSTRING(@products, 0, PATINDEX('%|%',@products))
        SELECT @individual

        SET @products = SUBSTRING(@products, LEN(@individual + '|') + 1,
                                                     LEN(@products))
    END
    ELSE
    BEGIN
        SET @individual = @products
        SET @products = NULL
        SELECT @individual
    END
END
 

95voto

vzczc Puntos 4923

En primer lugar, cree una función (usando CTE, expresión de tabla común elimina la necesidad de una tabla temporal)

  create function dbo.SplitString 
    (
        @str nvarchar(4000), 
        @separator char(1)
    )
    returns table
    AS
    return (
        with tokens(p, a, b) AS (
            select 
                1, 
                1, 
                charindex(@separator, @str)
            union all
            select
                p + 1, 
                b + 1, 
                charindex(@separator, @str, b + 1)
            from tokens
            where b > 0
        )
        select
            p-1 zeroBasedOccurance,
            substring(
                @str, 
                a, 
                case when b > 0 then b-a ELSE 4000 end) 
            AS s
        from tokens
      )
    GO
 

A continuación, utilizarlo como cualquier tabla (o modificar para que se ajuste dentro de su procedimiento almacenado existente) como este.

 select s 
from dbo.SplitString('Hello John Smith', ' ')
where zeroBasedOccurance=1
 

Actualización

Versión anterior sería un fracaso para la cadena de entrada de más de 4000 caracteres. Esta versión se hace cargo de la limitación:

 create function dbo.SplitString 
(
    @str nvarchar(max), 
    @separator char(1)
)
returns table
AS
return (
with tokens(p, a, b) AS (
    select 
        cast(1 as bigint), 
        cast(1 as bigint), 
        charindex(@separator, @str)
    union all
    select
        p + 1, 
        b + 1, 
        charindex(@separator, @str, b + 1)
    from tokens
    where b > 0
)
select
    p-1 ItemIndex,
    substring(
        @str, 
        a, 
        case when b > 0 then b-a ELSE LEN(@str) end) 
    AS Item
from tokens
);

GO
 

Uso sigue siendo el mismo.

31voto

Nathan Skerl Puntos 4441

Puede aprovechar una mesa Número de hacer el análisis de cadenas velocidad del rayo:

     create function [dbo].[ufn_ParseArray]
    (	@Input		nvarchar(4000), 
    	@Delimiter	char(1) = ',',
    	@BaseIdent	int
    )
returns table as
return  
    (	select	row_number() over (order by n desc) + (@BaseIdent - 1) [i],
    			substring(@Input, n, charindex(@Delimiter, @Input + @Delimiter, n) - n) s
    	from	dbo.Number
    	where	n <= convert(int, len(@Input)) and
    			substring(@Delimiter + @Input, n, 1) = @Delimiter
    )
 

Uso:

 declare @Array varchar(500)
set @Array = 'Hello John smith'

select  s 
from    dbo.ufn_ParseArray(@Array, ' ', 0)
where   i = 1
 

19voto

brendan Puntos 15097

Aquí está una UDF que lo hará. Volverá una tabla de los valores delimitados, no he probado todos los escenarios en él, pero su ejemplo funciona bien.

 

Usted lo llamaría así:

 CREATE FUNCTION SplitString  

Edit: Solución Actualización para manejar delimters con un len> 1 como en:

 

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X