Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Używając T-SQL, zwróć n-ty oddzielony element z łańcucha

Jest to najłatwiejsza odpowiedź na odzyskanie 67 (bezpieczne dla typu!! ):

SELECT CAST('<x>' + REPLACE('1,222,2,67,888,1111',',','</x><x>') + '</x>' AS XML).value('/x[4]','int')

Poniżej znajdziesz przykłady, jak używać tego ze zmiennymi dla łańcucha, ogranicznika i pozycji (nawet w przypadku skrajnych przypadków ze znakami zabronionymi w XML)

Łatwy

To pytanie nie dotyczy metody dzielenia ciągów , ale o jak uzyskać n-ty element . Najłatwiejszym, w pełni nieliniowym sposobem byłoby to IMO:

To jest prawdziwy jednowiersz aby część 2 była oddzielona spacją:

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

Zmiennych można używać z sql:variable() lub sql:column()

Oczywiście możesz używać zmiennych dla ogranicznika i pozycji (użyj sql:column aby pobrać pozycję bezpośrednio z wartości zapytania):

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

Obudowa krawędziowa ze znakami zabronionymi w XML

Jeśli Twój ciąg może zawierać zabronione znaki , nadal możesz to zrobić w ten sposób. Po prostu użyj FOR XML PATH na swoim łańcuchu, aby niejawnie zastąpić wszystkie zabronione znaki pasującą sekwencją ucieczki.

Jest to bardzo szczególny przypadek, jeśli – dodatkowo – twoim ogranicznikiem jest średnik . W tym przypadku najpierw zamieniam ogranicznik na „#DLMT#”, a na końcu zamieniam go na znaczniki 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)');

AKTUALIZACJA dla SQL-Server 2016+

Niestety programiści zapomnieli zwrócić indeks części za pomocą STRING_SPLIT . Ale używając SQL-Server 2016+, istnieje JSON_VALUE i OPENJSON .

Z JSON_VALUE możemy przekazać pozycję jako tablicę indeksu.

Dla OPENJSON dokumentacja wyraźnie stwierdza:

Gdy OPENJSON analizuje tablicę JSON, funkcja zwraca indeksy elementów w tekście JSON jako klucze.

Ciąg taki jak 1,2,3 nie potrzebuje niczego więcej niż nawiasy:[1,2,3] .
Ciąg słów takich jak this is an example musi być ["this","is","an"," example"] .
Są to bardzo proste operacje na łańcuchach. Po prostu wypróbuj:

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,']'));

--Zobacz to dla bezpiecznego dzielenia ciągów znaków (od zera ):

SELECT  JsonArray.[key] AS [Position]
       ,JsonArray.[value] AS [Part]
FROM OPENJSON('["' + REPLACE(@str,' ','","') + '"]') JsonArray

W tym poście przetestowałem różne podejścia i stwierdziłem, że OPENJSON jest naprawdę szybki. Nawet znacznie szybciej niż słynna metoda "delimitedSplit8k()"...

AKTUALIZACJA 2 — Uzyskaj wartości bezpieczne dla typu

Możemy użyć tablicy w tablicy po prostu używając podwojonego [[]] . Pozwala to na wpisanie WITH -klauzula:

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


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Zbieranie danych o wydajności za pomocą narzędzia SQLDiag | Rozwiązywanie problemów z wydajnością serwera SQL -6

  2. Jak sprawdzić, czy IDENTITY_INSERT jest ustawione na ON lub OFF w SQL Server?

  3. Jak wykonać kopię zapasową i przywrócić bazę danych jako kopię na tym samym serwerze?

  4. Konwertuj „smalldatetime” na „time” w SQL Server (przykłady T-SQL)

  5. Automatyczne usuwanie zapomnianych transakcji w MS SQL Server