これは 67 を解放する最も簡単な答えです (タイプセーフ!! ):
SELECT CAST('<x>' + REPLACE('1,222,2,67,888,1111',',','</x><x>') + '</x>' AS XML).value('/x[4]','int')
以下に、文字列、区切り文字、および位置の変数でこれを使用する方法の例を示します (XML で禁止されている文字を含むエッジケースの場合でも)。
簡単なもの
この質問は、文字列の分割方法に関するものではなく、n 番目の要素を取得する方法に関するものです。最も簡単で完全にインライン化可能な方法は、次の IMO です。
これは、スペースで区切られたパート 2 を取得する実際のワンライナーです。
DECLARE @input NVARCHAR(100)=N'part1 part2 part3';
SELECT CAST(N'<x>' + REPLACE(@input,N' ',N'</x><x>') + N'</x>' AS XML).value('/x[2]','nvarchar(max)')
sql:variable()
変数はまたはで使用できますsql:column()
もちろん、区切り文字と位置に変数を使用できますsql:column
(クエリの値から直接位置を取得するために使用します)。
DECLARE @dlmt NVARCHAR(10)=N' ';
DECLARE @pos INT = 2;
SELECT CAST(N'<x>' + REPLACE(@input,@dlmt,N'</x><x>') + N'</x>' AS XML).value('/x[sql:variable("@pos")][1]','nvarchar(max)')
XML 禁止文字を含む Edge-Case
文字列に禁止文字が含まれている可能性がある場合でも、この方法で行うことができます。最初に文字列で使用FOR XML PATH
して、禁止されているすべての文字を適切なエスケープシーケンスに暗黙的に置き換えます。
さらに、区切り文字がセミコロンである場合は、非常に特殊なケースです。この場合、最初に区切り文字を「#DLMT#」に置き換え、最後にこれを XML タグに置き換えます。
SET @input=N'Some <, > and &;Other äöü@€;One more';
SET @dlmt=N';';
SELECT CAST(N'<x>' + REPLACE((SELECT REPLACE(@input,@dlmt,'#DLMT#') AS [*] FOR XML PATH('')),N'#DLMT#',N'</x><x>') + N'</x>' AS XML).value('/x[sql:variable("@pos")][1]','nvarchar(max)');
SQL Server 2016+ の更新
残念ながら、開発者は でパーツのインデックスを返すのを忘れていましたSTRING_SPLIT
。しかし、SQL-Server 2016+ を使用するとJSON_VALUE
、OPENJSON
.
JSON_VALUE
インデックスの配列として位置を渡すことができます。
ドキュメントには明確にOPENJSON
記載されています:
OPENJSON が JSON 配列を解析すると、関数は JSON テキスト内の要素のインデックスをキーとして返します。
のような文字列に1,2,3
は、角かっこ以外は何も必要ありません: [1,2,3]
.
のような単語の文字列は、 であるthis is an example
必要があります["this","is","an"," example"]
。
これらは非常に簡単な文字列操作です。試してみてください:
DECLARE @str VARCHAR(100)='Hello John Smith';
DECLARE @position INT = 2;
--We can build the json-path '$[1]' using CONCAT
SELECT JSON_VALUE('["' + REPLACE(@str,' ','","') + '"]',CONCAT('$[',@position-1,']'));
--位置セーフな文字列スプリッター (ゼロベース) については、これを参照してください。
SELECT JsonArray.[key] AS [Position]
,JsonArray.[value] AS [Part]
FROM OPENJSON('["' + REPLACE(@str,' ','","') + '"]') JsonArray
この投稿では、さまざまなアプローチをテストし、それOPENJSON
が非常に高速であることを発見しました。有名な「delimitedSplit8k()」メソッドよりもはるかに高速です...
UPDATE 2 - タイプセーフな値を取得する
doubled を使用するだけで、配列内で配列[[]]
を使用できます。これにより、型付きWITH
-clauseが可能になります。
DECLARE @SomeDelimitedString VARCHAR(100)='part1|1|20190920';
DECLARE @JsonArray NVARCHAR(MAX)=CONCAT('[["',REPLACE(@SomeDelimitedString,'|','","'),'"]]');
SELECT @SomeDelimitedString AS TheOriginal
,@JsonArray AS TransformedToJSON
,ValuesFromTheArray.*
FROM OPENJSON(@JsonArray)
WITH(TheFirstFragment VARCHAR(100) '$[0]'
,TheSecondFragment INT '$[1]'
,TheThirdFragment DATE '$[2]') ValuesFromTheArray