web-dev-qa-db-fra.com

STRING_SPLIT dans SQL Server 2012

J'ai ce paramètre

@ID varchar = ‘1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20’ 

Je veux faire quelque chose pour diviser les valeurs séparées par des virgules.

La fonction string_split ne fonctionne pas et j'obtiens cette erreur:

La fonction STRING_SPLIT est disponible uniquement sous le niveau de compatibilité 130

et j'essaie de modifier ma base de données et de définir la compatibilité sur 130 mais je ne dispose pas de l'autorisation nécessaire pour ce changement. 

5
Moh

Une autre approche consiste à utiliser aussi la méthode XML avec CROSS APPLY pour fractionner vos données séparées par des virgules:

SELECT Split.a.value('.', 'NVARCHAR(MAX)') DATA
FROM
(
    SELECT CAST('<X>'+REPLACE(@ID, ',', '</X><X>')+'</X>' AS XML) AS String
) AS A
CROSS APPLY String.nodes('/X') AS Split(a);

Résultat :

DATA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

Exemple :

DECLARE @ID NVARCHAR(300)= '1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20';
DECLARE @Marks NVARCHAR(300)= '0,1,2,5,8,9,4,6,7,3,5,2,7,1,9,4,0,2,5,0';
DECLARE @StudentsMark TABLE
(id    NVARCHAR(300),
 marks NVARCHAR(300)
); 
--insert into @StudentsMark 
;WITH CTE
     AS (
     SELECT Split.a.value('.', 'NVARCHAR(MAX)') id,
            ROW_NUMBER() OVER(ORDER BY
                             (
                                 SELECT NULL
                             )) RN
     FROM
     (
         SELECT CAST('<X>'+REPLACE(@ID, ',', '</X><X>')+'</X>' AS XML) AS String
     ) AS A
     CROSS APPLY String.nodes('/X') AS Split(a)),
     CTE1
     AS (
     SELECT Split.a.value('.', 'NVARCHAR(MAX)') marks,
            ROW_NUMBER() OVER(ORDER BY
                             (
                                 SELECT NULL
                             )) RN
     FROM
     (
         SELECT CAST('<X>'+REPLACE(@Marks, ',', '</X><X>')+'</X>' AS XML) AS String
     ) AS A
     CROSS APPLY String.nodes('/X') AS Split(a))
     INSERT INTO @StudentsMark
            SELECT C.id,
                   C1.marks
            FROM CTE C
                 LEFT JOIN CTE1 C1 ON C1.RN = C.RN;
SELECT *
FROM @StudentsMark;
12
Yogesh Sharma

Une petite variation du polyfill de @ Al3x_M, quand il n'est pas possible de changer le niveau de compatibilité de la base de données: J'utilise une variable TABLE pour stocker la liste de valeurs, pour pouvoir les utiliser plus tard dans une autre requête:

DECLARE @IDs VARCHAR(500);
SET @IDs = '1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,2a0' ;

declare @list TABLE (id int);
DECLARE @Number int, @idx int
DECLARE @charSpliter CHAR;

SET @charSpliter = ','
SET @IDs = @IDs + @charSpliter;
set  @idx = 0

WHILE (1 = 1)
    BEGIN
        set  @idx =  CHARINDEX(@charSpliter, @IDs)
        if (@idx is NULL or @idx <= 0) break;

        BEGIN TRY
        SET @Number = SUBSTRING(@IDs, 0, @idx)
        SET @IDs = SUBSTRING(@IDs, @idx + 1, LEN(@IDs))

        insert @list select convert(int, @Number)
    END TRY  
    BEGIN CATCH 
        break
    END CATCH  
END

-- @list available for the next query...
select * from  @list
0
Didier68

Si le niveau de compatibilité de votre base de données est inférieur à 130 , SQL Server ne pourra pas trouver et exécuter la fonction STRING_SPLIT. Vous pouvez modifier un niveau de compatibilité de la base de données à l'aide de la commande suivante:

ALTER DATABASE DatabaseName SET COMPATIBILITY_LEVEL = 130

Notez que le niveau de compatibilité 120 peut être défini par défaut, même dans les nouvelles bases de données SQL Azure.

Pour référence:

Version - Niveau de compatibilité le plus élevé - Niveau disponible le plus bas

SQL 2017 - 140 - 100
SQL 2016 - 130 - 100
SQL 2014 - 120 - 100
SQL 2012 - 110 - 90
SQL 2008 - 100 - 80
SQL 2005 - 90 - 80
SQL 2000 - 80 - 80

Vérifiez également votre syntaxe, comme suit: 

SELECT Value FROM STRING_SPLIT('Lorem ipsum dolor sit amet.', ' ');
0
hamzox

Une autre approche consisterait à utiliser CHARINDEX et SUBSTRING dans un WHILE:

DECLARE @IDs VARCHAR(500);
DECLARE @Number VARCHAR(500);
DECLARE @charSpliter CHAR;

SET @charSpliter = ','
SET @IDs = '1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20' + @charSpliter;

WHILE CHARINDEX(@charSpliter, @IDs) > 0
BEGIN
    SET @Number = SUBSTRING(@IDs, 0, CHARINDEX(@charSpliter, @IDs))
    SET @IDs = SUBSTRING(@IDs, CHARINDEX(@charSpliter, @IDs) + 1, LEN(@IDs))

    PRINT @Number

END
0
Al3x_M