STRING_SPLIT mit einem Trennzeichen aus mehreren Zeichen?

9

In SQL Server 2016 wurde STRING_SPLIT eingeführt, das sehr schnell ist und einen hervorragenden Ersatz für alle hausgemachten Implementierungsaufgaben darstellt, die vor 2016 ausgeführt werden.

Leider unterstützt STRING_SPLIT nur ein Einzelzeichen-Trennzeichen, was nicht immer ausreicht. Kennt jemand eine gute Implementierung, die die Verwendung mehrerer Zeichen im Trennzeichen ermöglicht?

Petter Brodin
quelle

Antworten:

20

Nun, Sie können REPLACEdem Argument immer ein Einzelzeichen-Trennzeichen hinzufügen, bevor Sie es übergeben. Sie müssen nur ein Zeichen auswählen, das in den tatsächlichen Daten wahrscheinlich / unmöglich erscheint. Nehmen wir in diesem Beispiel an, Ihre Originaldaten verwenden drei Pipes als Trennzeichen. Ich habe zufällig ein Unicode-Zeichen ausgewählt, um Folgendes zu ersetzen:

DECLARE 
  @olddelim nvarchar(32) = N'|||', 
  @newdelim nchar(1)     = NCHAR(9999); -- pencil (✏)

DECLARE @x nvarchar(max) = N'foo|||bar|||blat|||splunge';

SELECT * FROM STRING_SPLIT(REPLACE(@x, @olddelim, @newdelim), @newdelim);

Ich habe hier ausführlicher darüber gebloggt:


Kommentar adressieren:

schlechte Lösung. Was ist, wenn die ursprüngliche Zeichenfolge wie 'abc || pqr ||| rst || 123' ist (dynamisch und kann alles enthalten)? Das gewünschte O / P ist 'abc || pqr' und 'rst || 123', aber Ihre Lösung ergibt 'abc' 'pqr' 'rst' '123'

Okay, nehmen wir Ihre Eingabe und sehen, ob meine Lösung die falsche Ausgabe erhält.

DECLARE 
  @olddelim nvarchar(32) = N'|||', 
  @newdelim nchar(1)     = NCHAR(9999); -- pencil (✏)

DECLARE @x nvarchar(max) = N'abc||pqr|||rst||123';

SELECT * FROM STRING_SPLIT(REPLACE(@x, @olddelim, @newdelim), @newdelim);

Ergebnis ist:

abc||pqr
rst||123

Und nicht das, was Sie angenommen haben müssen (aber nicht getestet haben):

abc
pqr
rst
123

Wenn sich Ihre Daten in einer Tabelle befinden, können Sie eine Ansicht erstellen, damit Sie diesen Ausdruck nicht in alle Ihre Abfragen einbeziehen müssen.


Wenn dies nicht funktioniert, weil Ihre Daten möglicherweise einen Stift ( ) enthalten und Sie in den 1.111.998 verfügbaren Unicode-Zeichen , die nicht in Ihrem Datensatz enthalten sind, kein einziges Zeichen finden , müssen Sie überspringen STRING_SPLIT(), da es fest codiert ist, ein einzelnes Zeichenbegrenzer ( separator Is a single character expression) zu akzeptieren .

Alternativen wurden hier schon Dutzende Male beantwortet , viele vorher STRING_SPLIT()existierten. Diese Methoden funktionieren immer noch.

Ich gehe STRING_SPLIT()in dieser Reihe auf viele Alternativen ein und diskutiere auch die Einschränkungen in (ich diskutiere auch, warum Sie in Betracht ziehen könnten, dies in T-SQL überhaupt nicht mit einer Methode zu tun):

Aaron Bertrand
quelle
schlechte Lösung. Was ist, wenn die ursprüngliche Zeichenfolge wie 'abc || pqr ||| rst || 123' ist (dynamisch und kann alles enthalten)? Das gewünschte O / P ist 'abc || pqr' und 'rst || 123', aber Ihre Lösung ergibt 'abc' 'pqr' 'rst' '123'
Jitendra Pancholi
@ Jitendra Hast du meine ganze Antwort gelesen? You just need to choose a character that is unlikely/impossible to appear in the actual data.Unicode hat 1.111.998 mögliche Zeichen zur Auswahl, aber wenn Sie wirklich kein einziges Zeichen finden können, das nicht in den Daten enthalten ist (oder nicht zuerst in den Daten ersetzt werden kann, während der ETL oder so), benötigen Sie ein anderer Ansatz (wie die vielen, auf die ich in meiner Antwort verwiesen habe). Ich freue mich auf Ihre bessere Lösung.
Aaron Bertrand
Immer noch nicht gut, Sie können sich nicht 100% sicher sein, was das Trennzeichen betrifft, und davon ausgehen, dass dieses Trennzeichen ohnehin kein Teil der Zeichenfolge ist.
Jitendra Pancholi
1
Manchmal möchten Sie einfach nur string_split () ¯ \ _ (ツ) _ / ¯ verwenden
Peter Vandivier
3
@JitendraPancholi Sie sind technisch korrekt, aber Sie sind hier unfair, weil: 1) die Einschränkung bei STRING_SPLIT, nicht bei dieser speziellen Umgehung liegt , 2) bei dieser Frage geht es darum STRING_SPLIT, nicht mit Trennzeichen für mehrere Zeichen im Allgemeinen zu arbeiten, 3) bei In der Praxis kann man davon ausgehen, dass bestimmte Zeichen nicht vorhanden sind, andernfalls handelt es sich nur um schlechte Daten. 4) NCHAR(31) (Datensatztrennzeichen) sollte sicher sein, da dies der Zweck ist, oder NCHAR(0)mit, , @newdelim COLLATE Latin1_General_100_BIN2);wenn U + 0000 (null) in einer Zeichenfolge enthalten ist Daten, dann gibt es größere Probleme!
Solomon Rutzky