web-dev-qa-db-ja.com

SQL Server 2012のSTRING_SPLIT

このパラメーターがあります

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

コンマ区切りの値を分割するために何かしたいのですが。

string_split関数が機能せず、次のエラーが表示されます。

STRING_SPLIT関数は、互換性レベル130でのみ使用可能です

データベースを変更して互換性を130に設定しようとしましたが、この変更の許可がありません。

10
Moh

他のアプローチでは、XMLメソッドとCROSS APPLYを使用して、カンマ区切りデータを分割することもできます。

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);

結果:

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

例:

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;
18
Yogesh Sharma

データベースの互換性レベルを変更できない場合の@ Al3x_Mのポリフィルの少しのバリエーション:後で別のクエリで使用するために、値のリストを格納するためにTABLE変数を使用します。

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

データベースの互換性レベルが1より低い場合、SQL ServerはSTRING_SPLIT関数を見つけて実行できません。次のコマンドを使用して、データベースの互換性レベルを変更できます。

ALTER DATABASE DatabaseName SET COMPATIBILITY_LEVEL = 130

新しいAzure SQL Databasesでも、互換性レベル120がデフォルトになる場合があることに注意してください。

参考のため:

バージョン-最高の互換性レベル-最低の利用可能レベル

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

また、次のような構文も確認してください。

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

別のアプローチは、WHILEでCHARINDEXとSUBSTRINGを使用することです。

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