Bei dieser Frage geht es nicht um einen String-Split-Ansatz , sondern darum, wie das n-te Element erhalten wird .
Alle Antworten hier sind eine Art von String - Splitting zu tun Rekursion, CTE
s, mehrere CHARINDEX
, REVERSE
und PATINDEX
, erfinden Funktionen, Aufruf für CLR Methoden, Zahlentabellen, CROSS APPLY
s ... Die meisten Antworten viele Zeilen Code.
Aber - wenn Sie wirklich nur einen Ansatz wollen, um das n-te Element zu erhalten - kann dies als echter Einzeiler , ohne UDF, nicht einmal als Unterauswahl erfolgen ... und als zusätzlichen Vorteil: Typensicher
Holen Sie sich Teil 2 durch ein Leerzeichen begrenzt:
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)')
Natürlich können Sie Variablen für Trennzeichen und Position verwenden (verwenden Sie sql:column
diese Option, um die Position direkt aus dem Wert einer Abfrage abzurufen):
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)')
Wenn Ihre Zeichenfolge möglicherweise verbotene Zeichen enthält (insbesondere eines davon &><
), können Sie dies dennoch auf diese Weise tun. Verwenden FOR XML PATH
Sie einfach zuerst Ihre Zeichenfolge, um alle verbotenen Zeichen implizit durch die passende Escape-Sequenz zu ersetzen.
Es ist ein ganz besonderer Fall, wenn - zusätzlich - Ihr Trennzeichen das Semikolon ist . In diesem Fall ersetze ich das Trennzeichen zuerst durch '# DLMT #' und ersetze es schließlich durch die XML-Tags:
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)');
UPDATE für SQL-Server 2016+
Leider haben die Entwickler vergessen, den Index des Teils mit zurückzugeben STRING_SPLIT
. Bei Verwendung von SQL-Server 2016+ gibt es jedoch JSON_VALUE
und OPENJSON
.
Mit können JSON_VALUE
wir die Position als Index-Array übergeben.
In OPENJSON
der Dokumentation heißt es deutlich:
Wenn OPENJSON ein JSON-Array analysiert, gibt die Funktion die Indizes der Elemente im JSON-Text als Schlüssel zurück.
Ein String wie 1,2,3
braucht nichts weiter als Klammern : [1,2,3]
.
Eine Reihe von Wörtern wie this is an example
muss sein ["this","is","an","example"]
.
Dies sind sehr einfache Zeichenfolgenoperationen. Probieren Sie es einfach aus:
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,']'));
--See dies für eine sichere Position strangTeiler ( Null-Basis ):
SELECT JsonArray.[key] AS [Position]
,JsonArray.[value] AS [Part]
FROM OPENJSON('["' + REPLACE(@str,' ','","') + '"]') JsonArray
In diesem Beitrag habe ich verschiedene Ansätze getestet und festgestellt, dass OPENJSON
das sehr schnell geht. Noch viel schneller als die berühmte Methode "delimitedSplit8k ()" ...
UPDATE 2 - Holen Sie sich die Werte typsicher
Wir können ein Array innerhalb eines Arrays verwenden , indem wir einfach double verwenden [[]]
. Dies ermöglicht eine typisierte WITH
Klausel:
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