Diese Frage dreht sich nicht um einen String-Split-Ansatz, sondern darum, wie man das n-te Element erhält.
Die meisten Antworten hier verwenden irgendeine Form von String-Splitting mit Rekursion, CTE
s, mehrere CHARINDEX
, REVERSE
und PATINDEX
, erfinden Funktionen, rufen CLR-Methoden auf, verwenden Nummertabellen, CROSS APPLY
... Die meisten Antworten bestehen aus vielen Codezeilen.
Aber - wenn du wirklich nichts weiter als einen Ansatz benötigst, um das n-te Element zu erhalten - kann dies als echter Einzeiler gemacht werden, keine UDF, nicht einmal ein Sub-Select... Und als zusätzlicher Vorteil: typsicher
Hole Teil 2, der durch ein Leerzeichen begrenzt ist:
DECLARE @input NVARCHAR(100)=N'part1 part2 part3';
SELECT CAST(N'' + REPLACE(@input,N' ',N'') + N'' AS XML).value('/x[2]','nvarchar(max)')
Natürlich kannst du Variablen verwenden für das Trennzeichen und die Position (verwende sql:column
, um die Position direkt aus dem Wert einer Abfrage abzurufen):
DECLARE @dlmt NVARCHAR(10)=N' ';
DECLARE @pos INT = 2;
SELECT CAST(N'' + REPLACE(@input,@dlmt,N'') + N'' AS XML).value('/x[sql:variable("@pos")][1]','nvarchar(max)')
Wenn dein String möglicherweise verbotene Zeichen enthält (insbesondere eines unter &><
), kannst du es trotzdem auf diese Weise tun. Verwende einfach zuerst FOR XML PATH
auf deinem String, um alle verbotenen Zeichen implizit durch die passende Escape-Sequenz zu ersetzen.
Es ist ein sehr spezieller Fall, wenn - zusätzlich - dein Trennzeichen das Semikolon ist. In diesem Fall ersetze ich das Trennzeichen zuerst durch '#DLMT#' und ersetze dies schließlich durch die XML-Tags:
SET @input=N'Some <, > and &;Other äöü@€;One more';
SET @dlmt=N';';
SELECT CAST(N'' + REPLACE((SELECT REPLACE(@input,@dlmt,'#DLMT#') AS [*] FOR XML PATH('')),N'#DLMT#',N'') + N'' AS XML).value('/x[sql:variable("@pos")][1]','nvarchar(max)');
UPDATE für SQL-Server 2016+
Bedauerlicherweise haben die Entwickler vergessen, den Index des Teils mit STRING_SPLIT
zurückzugeben. Aber, unter Verwendung von SQL-Server 2016+ gibt es JSON_VALUE
und OPENJSON
.
Mit JSON_VALUE
können wir die Position als Index-Array übergeben.
Für OPENJSON
besagt die Dokumentation klar:
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]
.
Ein String von Wörtern wie this is an example
muss als ["this","is","an","example"]
vorliegen.
Dies sind sehr einfache Zeichenkettenoperationen. Probiere es einfach aus:
DECLARE @str VARCHAR(100)='Hello John Smith';
DECLARE @position INT = 2;
--Wir können den JSON-Pfad '$[1]' mit CONCAT aufbauen
SELECT JSON_VALUE('["' + REPLACE(@str,' ','","') + '"]',CONCAT('$[',@position-1,']'));
--Siehe dies für einen positions sicheren String-Splitter (nullbasiert):
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
wirklich schnell ist. Sogar viel schneller als die berühmte "delimitedSplit8k()" Methode...
UPDATE 2 - Die Werte typsicher abrufen
Wir können ganz einfach ein Array innerhalb eines Arrays durch die Verwendung von verdoppelten [[]]
erstellen. Dies ermöglicht eine getypte 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
3 Stimmen
Siehe stackoverflow.com/questions/314824/… ebenfalls
5 Stimmen
Die höchsten Antworten hier sind - zumindest für mich - ziemlich altmodisch und eher veraltet. Prozedurale Logik, Schleifen, Rekursionen, CLR, Funktionen, viele Codezeilen... Es könnte interessant sein, die "aktiven" Antworten zu lesen, um aktuellere Ansätze zu finden.
0 Stimmen
Ich habe eine neue Antwort mit einem aktuelleren Ansatz hinzugefügt: stackoverflow.com/a/49669994/632604
0 Stimmen
Versuchen Sie Holen Sie sich das n-te Element einer Liste -> portosql.wordpress.com/2019/05/27/enesimo-elemento-lista
0 Stimmen
Einige Kommentare (einschließlich eines von mir) wurden gelöscht. Möchte sich einer der Moderatoren äußern?
1 Stimmen
@TimAbell, die Dokumentation besagt, dass "Die Reihenfolge entspricht möglicherweise nicht der Reihenfolge der Teilzeichenfolgen im Eingabestring".
0 Stimmen
@TimAbell Ja, ja... aber wie erhält man ein EINZELNES Ergebnis nach Index aus dem Ergebnis von
STRING_SPLIT
???0 Stimmen
Bis zur SQL Server 2022 ist die zuverlässigste Lösung
string_split
mit Ordinal. Siehe stackoverflow.com/a/70196925/87015