Mam kolumnę SQL Server 2008 R2 zawierającą ciąg, który muszę podzielić przecinkiem. Widziałem wiele odpowiedzi na StackOverflow, ale żadna z nich nie działa w R2. Upewniłem się, że mam uprawnienia do wybierania dowolnych przykładów funkcji podziału. Każda pomoc mile widziana.
sql
sql-server
tsql
sql-server-2008
split
Lee Grindon
źródło
źródło
mdq.RegexSplit
dodatku „Master Data Services” znajduje się funkcja, która może pomóc. Z pewnością warte zbadania .Odpowiedzi:
Używałem wcześniej tego SQL, który może Ci pomóc: -
i używać: -
źródło
Zamiast rekurencyjnych CTE i pętli while, czy ktoś rozważał podejście bardziej oparte na zbiorach? Zauważ, że ta funkcja została napisana dla pytania, które było oparte na SQL Server 2008 i przecinku jako separatorze . W programie SQL Server 2016 i nowszych (oraz na poziomie zgodności 130 i nowszych)
STRING_SPLIT()
jest lepszą opcją .Jeśli chcesz uniknąć ograniczenia długości ciągu wynoszącej <= liczba wierszy w
sys.all_columns
(9 980 calimodel
w programie SQL Server 2017; znacznie więcej we własnych bazach danych użytkowników), możesz użyć innych metod wyprowadzania liczb, takich jak budowanie własnej tabeli liczb . Możesz również użyć rekurencyjnego CTE w przypadkach, gdy nie możesz używać tabel systemowych lub tworzyć własnych:Ale będziesz musiał dołączyć
OPTION (MAXRECURSION 0)
(lubMAXRECURSION <longest possible string length if < 32768>
) do zewnętrznego zapytania, aby uniknąć błędów z rekurencją dla ciągów> 100 znaków. Jeśli to również nie jest dobra alternatywa, zobacz tę odpowiedź, jak wskazano w komentarzach.(Również separator będzie musiał być
NCHAR(<=1228)
. Wciąż szukam przyczyny).Więcej o funkcjach rozdzielania, dlaczego (i udowodnij, że), podczas gdy pętle i rekurencyjne CTE nie skalują się i lepsze alternatywy, jeśli dzielisz ciągi pochodzące z warstwy aplikacji:
źródło
sys.all_objects
jest mniejsza niż liczba znaków w ciągu wejściowym, spowoduje to obcięcie ciągu i zniknięcie wartości. Ponieważsys.all_objects
jest używany tylko jako sztuczka do generowania wierszy, istnieją lepsze sposoby, aby to zrobić, np. Ta odpowiedź .Wreszcie czekanie dobiegło końca w SQL Server 2016 wprowadzili funkcję Split string:
STRING_SPLIT
Wszystkie inne metody dzielenia ciągów, takie jak XML, tabela Tally, pętla while itp., Zostały zdmuchnięte przez tę
STRING_SPLIT
funkcję.Oto doskonały artykuł z porównaniem wydajności: Niespodzianki dotyczące wydajności i założenia: STRING_SPLIT
źródło
Najłatwiej to zrobić, używając
XML
formatu.1. Konwersja łańcucha do wierszy bez tabeli
PYTANIE
WYNIK
2. Konwersja do wierszy z tabeli, które mają identyfikator dla każdego wiersza CSV
TABELA ŹRÓDEŁ
PYTANIE
WYNIK
źródło
@String
zawiera zabronione znaki ... Właśnie opublikowałem odpowiedź, aby rozwiązać ten problem.Potrzebowałem szybkiego sposobu na pozbycie
+4
się kodu pocztowego .Bez proc ... bez UDF ... tylko jedno małe polecenie wbudowane, które robi to, co musi. Nie wyszukane, nie eleganckie.
Zmień separator w razie potrzeby itp. I będzie działać na wszystko.
źródło
jeśli wymienisz
z
możesz wyeliminować ostatnią wstawkę po pętli while!
źródło
+1
doSELECT @pos = LEN(@stringToSplit)
wydaje się rozwiązać ten problem. JednakSELECT @stringToSplit = SUBSTRING(@stringToSplit, @pos+1, LEN(@stringToSplit)-@pos)
zwróci,Invalid length parameter passed to the LEFT or SUBSTRING function
chyba że dodasz również+1
do trzeciego parametru SUBSTRING. lub możesz zamienić to przypisanie naSET @stringToSplit = SUBSTRING(@stringToSplit, @pos+1, 4000) --MAX len of nvarchar is 4000
Wszystkie funkcje do dzielenia ciągów, które używają pewnego rodzaju pętli (iteracji), mają złą wydajność. Należy je zastąpić rozwiązaniem opartym na zestawie.
Ten kod działa doskonale.
źródło
@List
zawiera zabronione znaki ... Właśnie opublikowałem odpowiedź, aby rozwiązać ten problem.Często używane podejście z elementami XML nie działa w przypadku zabronionych znaków. Jest to podejście do używania tej metody z dowolnym rodzajem znaku, nawet ze średnikiem jako separatorem.
Sztuczka polega na tym, że najpierw należy użyć,
SELECT SomeString AS [*] FOR XML PATH('')
aby wszystkie zabronione postacie prawidłowo uciekły. To jest powód, dla którego zastępuję ogranicznik magiczną wartością, aby uniknąć problemów z;
ogranicznikiem.Wynik
źródło
Ostatnio musiałem coś takiego napisać. Oto rozwiązanie, które wymyśliłem. Jest uogólniony dla dowolnego ciągu separatora i myślę, że działałby nieco lepiej:
źródło
Rozwiązanie wykorzystujące CTE, gdyby ktoś tego potrzebował (oprócz mnie, który oczywiście to zrobił, dlatego to napisałem).
źródło
Jest to węższy sposób. Kiedy to robię, zwykle mam rozdzieloną przecinkami listę unikalnych identyfikatorów (INT lub BIGINT), które chcę rzutować jako tabelę, aby użyć jej jako sprzężenia wewnętrznego do innej tabeli, która ma klucz podstawowy INT lub BIGINT. Chcę, aby funkcja z wartościami przechowywanymi w tabeli została zwrócona, aby uzyskać jak najbardziej wydajne sprzężenie.
Przykładowe użycie to:
Ukradłem ten pomysł z http://sqlrecords.blogspot.com/2012/11/converting-delimited-list-to-table.html , zmieniając go tak, aby był wartościowany w tabeli i rzutowany jako INT.
źródło
Jest tutaj poprawna wersja, ale pomyślałem, że byłoby miło dodać trochę tolerancji na błędy w przypadku, gdy mają końcowy przecinek, a także zrobić to, abyś mógł go używać nie jako funkcji, ale jako części większego fragmentu kodu . Na wypadek, gdybyś używał go tylko raz i nie potrzebujesz funkcji. Dotyczy to również liczb całkowitych (do tego potrzebowałem), więc być może będziesz musiał zmienić typy danych.
źródło
SET @StringToSeperate = @StringToSeperate+','
bezpośrednio przedWHILE
pętlą, myślę, że możesz być w stanie wyeliminować blok „dodaj ostatnią wartość”. Zobacz także mój sol'n na githubTrochę zmodyfikowałem + funkcję Andy Robinsona. Teraz możesz wybrać tylko wymaganą część z tabeli zwrotów:
SELECT Name FROM dbo.splitstring('ELIS.YD.CRP1.1.CBA.MDSP.T389.BT') WHERE numOrder=5
źródło
Jeśli potrzebujesz szybkiego rozwiązania ad hoc dla typowych przypadków z minimalnym kodem, to zrobi to ten rekurencyjny dwuwierszowy CTE:
Użyj tego jako samodzielnej instrukcji lub po prostu dodaj powyższe CTE do dowolnego zapytania, a będziesz mógł połączyć wynikową tabelę
b
z innymi w celu użycia w dalszych wyrażeniach.edytuj (przez Shnugo)
Jeśli dodasz licznik, wraz z Listą otrzymasz indeks pozycji:
Wynik:
źródło
Wybieram trasę xml, zawijając wartości w elementy (M, ale wszystko działa):
źródło
tutaj jest wersja, którą można podzielić na wzór przy użyciu patindex, prostej adaptacji powyższego postu. Miałem przypadek, w którym musiałem podzielić ciąg zawierający wiele znaków separatora.
wynik wygląda następująco
stringa stringb x y z
źródło
Osobiście używam tej funkcji:
źródło
Opracowałem podwójny rozdzielacz (zajmuje dwa rozdzielone znaki) zgodnie z żądaniem tutaj . Może mieć jakąś wartość w tym wątku, ponieważ jest najczęściej przywoływany w przypadku zapytań dotyczących dzielenia ciągów.
Stosowanie:
Możliwe użycie (pobierz drugą wartość każdego podziału):
źródło
Oto przykład, którego możesz użyć jako funkcji lub możesz również umieścić tę samą logikę w procedurze. --WYBIERZ * z [dbo] .fn_SplitString;
źródło
@vCSV
zawiera zabronione znaki ... Właśnie opublikowałem odpowiedź, aby rozwiązać ten problem.Rekurencyjne rozwiązanie oparte na cte
źródło
To jest oparte na odpowiedzi Andy'ego Robertsona, potrzebowałem separatora innego niż przecinek.
I aby z niego skorzystać:
(Testowane na SQL Server 2008 R2)
EDYCJA: poprawny kod testu
źródło
/ *
Przypadki testowe: patrz URL określany powyżej jako „rozszerzona funkcjonalność”
SELECT *,LEN(Item+'_')-1 'L' from splitstring('a,,b')
SELECT *,LEN(Item+'_')-1 'L' from splitstring('a,,')
SELECT *,LEN(Item+'_')-1 'L' from splitstring('a,, ')
SELECT *,LEN(Item+'_')-1 'L' from splitstring('a,, c ')
* /
źródło
źródło
Możesz użyć tej funkcji:
źródło
Z całym szacunkiem dla @AviG jest to opracowana przez niego wolna od błędów wersja funkcji zwracania wszystkich tokenów w całości.
źródło
Najłatwiejszy sposób:
Działa nawet w wydaniu ekspresowym :).
źródło