web-dev-qa-db-fra.com

Fractionner la chaîne dans le serveur SQL

J'ai une chaîne dans la base de données qui est séparée par des virgules. il n'y a aucun moyen efficace d'atteindre cet objectif.

16
rampuriyaaa

Essayez cette fonction

CREATE FUNCTION [dbo].[func_Split] 
    (   
    @DelimitedString    varchar(8000),
    @Delimiter              varchar(100) 
    )
RETURNS @tblArray TABLE
    (
    ElementID   int IDENTITY(1,1),  -- Array index
    Element     varchar(1000)               -- Array element contents
    )
AS
BEGIN

    -- Local Variable Declarations
    -- ---------------------------
    DECLARE @Index      smallint,
                    @Start      smallint,
                    @DelSize    smallint

    SET @DelSize = LEN(@Delimiter)

    -- Loop through source string and add elements to destination table array
    -- ----------------------------------------------------------------------
    WHILE LEN(@DelimitedString) > 0
    BEGIN

        SET @Index = CHARINDEX(@Delimiter, @DelimitedString)

        IF @Index = 0
            BEGIN

                INSERT INTO
                    @tblArray 
                    (Element)
                VALUES
                    (LTRIM(RTRIM(@DelimitedString)))

                BREAK
            END
        ELSE
            BEGIN

                INSERT INTO
                    @tblArray 
                    (Element)
                VALUES
                    (LTRIM(RTRIM(SUBSTRING(@DelimitedString, 1,@Index - 1))))

                SET @Start = @Index + @DelSize
                SET @DelimitedString = SUBSTRING(@DelimitedString, @Start , LEN(@DelimitedString) - @Start + 1)

            END
    END

    RETURN
END

Exemple d'utilisation - passez simplement à la fonction la chaîne délimitée par des virgules ainsi que le délimiteur requis.

DECLARE @SQLStr varchar(100)
SELECT @SQLStr = 'Mickey Mouse, Goofy, Donald Duck, Pluto, Minnie Mouse'

SELECT
    *
FROM
    dbo.func_split(@SQLStr, ',')

Le résultat sera comme ceci

Result

26
Vignesh Kumar A

... Puisqu'il n'y a pas de fonction intégrée dans le serveur SQL ...

C'était vrai au moment où vous avez posé cette question, mais SQL Server 2016 introduit STRING_SPLIT .

Vous pouvez donc simplement utiliser

SELECT value
FROM   STRING_SPLIT ('Apple,banana,pineapple,grapes', ',') 

Il y a quelques limitations (seuls les délimiteurs à un seul caractère sont acceptés et le manque de colonne indiquant que l'indice divisé est le plus accrocheur). Les diverses restrictions et certains résultats prometteurs des tests de performances se trouvent dans ce blog d'Aaron Bertrand .

15
Martin Smith

Vous pouvez convertir vos données en XML, en remplaçant la virgule par une balise personnalisée, dans ce cas, <w> pour Word.

create table t(col varchar(255));
insert into t values ('Apple,banana,pineapple,grapes');
insert into t values ('car,bike,airplane');

select cast(('<w>' + replace(col, ',', '</w><w>') + '</w>') as xml) as xmlValue
  from t

Qui revient

|                                               XMLVALUE |
|--------------------------------------------------------|
| <w>Apple</w><w>banana</w><w>pineapple</w><w>grapes</w> |
|                   <w>car</w><w>bike</w><w>airplane</w> |

Maintenant, si vous utilisez cette requête comme sélection XML interne, la requête externe peut la diviser en lignes distinctes:

Solution:

select split.xmlTable.value('.', 'varchar(255)') as xmlValue
from (

   select cast(('<w>' + replace(col, ',', '</w><w>') + '</w>') as xml) as xmlValue
     from t

) as xmlTable
cross apply xmlValue.nodes ('/w') as split(xmlTable);

sqlFiddle en direct

6
Jose Rui Santos

J'ai une solution utilisant Recursion comme suit

Create function split_string(@str as nvarchar(max),@separator as char(1)) returns @myvalues Table (id int identity(1,1),myval nvarchar(100))
as 
--Kamel Gazzah
--23/04/2019
begin
with cte as(
select @str [mystr],
cast(1 as int) [Start],
charindex(@separator,@str)as Nd
union all
select substring(@str,nd+1,len(@str)),cast(Nd+1 as int),charindex(@separator,@str,Nd+1) from cte
where nd>0
)
insert into @myvalues(myval) 
select case when nd>0 then substring(@str,start,Nd-start) 
else substring(@str,start,len(@str)) end [splitted] 
from cte   OPTION (MAXRECURSION 1000);
return ;
end;

Vous pouvez appeler cette fonction

select * from split_string('Apple,banana,pineapple,grapes',',')
0
Kemal AL GAZZAH