Using SQL Server, how do I split a string so I can access item x?
Take a string "Hello John Smith". How can I split the string by space and access the item at index 1 which should return "John"?
original title: "sql - How do I split a string so I can access item x?"
Using SQL Server, how do I split a string so I can access item x?
Take a string "Hello John Smith". How can I split the string by space and access the item at index 1 which should return "John"?
SQL Serverを使用して、アイテムxにアクセスできるように文字列を分割するにはどうすればよいですか?文字列 "Hello John Smith"を取ります。文字列をスペースで分割し、「John」を返す必要があるインデックス1のアイテムにアクセスするにはどうすればよいですか? ...
これは翻訳後の要約です。完全な翻訳を表示する必要がある場合は、「翻訳」アイコンをクリックしてください。
You may find the solution in SQL User Defined Function to Parse a Delimited String helpful (from The Code Project).
You can use this simple logic:
I don't believe SQL Server has a built-in split function, so other than a UDF, the only other answer I know is to hijack the PARSENAME function:
PARSENAME takes a string and splits it on the period character. It takes a number as its second argument, and that number specifies which segment of the string to return (working from back to front).
Obvious problem is when the string already contains a period. I still think using a UDF is the best way...any other suggestions?
First, create a function (using CTE, common table expression does away with the need for a temp table)
Then, use it as any table (or modify it to fit within your existing stored proc) like this.
Update
Previous version would fail for input string longer than 4000 chars. This version takes care of the limitation:
Usage remains the same.
Most of the solutions here use while loops or recursive CTEs. A set-based approach will be superior, I promise:
More on split functions, why (and proof that) while loops and recursive CTEs don't scale, and better alternatives, if splitting strings coming from the application layer:
On SQL Server 2016 or above, though, you should look at
STRING_SPLIT()
andSTRING_AGG()
:You can leverage a Number table to do the string parsing.
Create a physical numbers table:
Create test table with 1000000 rows
Create the function
Usage (outputs 3mil rows in 40s on my laptop)
cleanup
Performance here is not amazing, but calling a function over a million row table is not the best idea. If performing a string split over many rows I would avoid the function.
This question is not about a string split approach, but about how to get the nth element.
All answers here are doing some kind of string splitting using recursion,
CTE
s, multipleCHARINDEX
,REVERSE
andPATINDEX
, inventing functions, call for CLR methods, number tables,CROSS APPLY
s ... Most answers cover many lines of code.But - if you really want nothing more than an approach to get the nth element - this can be done as real one-liner, no UDF, not even a sub-select... And as an extra benefit: type safe
Get part 2 delimited by a space:
Of course you can use variables for delimiter and position (use
sql:column
to retrieve the position directly from a query's value):If your string might include forbidden characters (especially one among
&><
), you still can do it this way. Just useFOR XML PATH
on your string first to replace all forbidden characters with the fitting escape sequence implicitly.It's a very special case if - additionally - your delimiter is the semicolon. In this case I replace the delimiter first to '#DLMT#', and replace this to the XML tags finally:
UPDATE for SQL-Server 2016+
Regretfully the developers forgot to return the part's index with
STRING_SPLIT
. But, using SQL-Server 2016+, there isJSON_VALUE
andOPENJSON
.With
JSON_VALUE
we can pass in the position as the index' array.For
OPENJSON
the documentation states clearly:A string like
1,2,3
needs nothing more than brackets:[1,2,3]
.A string of words like
this is an example
needs to be["this","is","an","example"]
.These are very easy string operations. Just try it out:
--See this for a position safe string-splitter (zero-based):
In this post I tested various approaches and found, that
OPENJSON
is really fast. Even much faster than the famous "delimitedSplit8k()" method...Here is a UDF which will do it. It will return a table of the delimited values, haven't tried all scenarios on it but your example works fine.
You would call it like this:
Edit: Updated solution to handle delimters with a len>1 as in :
Here I post a simple way of solution
Execute the function like this
In my opinion you guys are making it way too complicated. Just create a CLR UDF and be done with it.
What about using
string
andvalues()
statement?Result-set achieved.
I use the answer of frederic but this did not work in SQL Server 2005
I modified it and I'm using
select
withunion all
and it worksAnd the result-set is:
This pattern works fine and you can generalize
note FIELD, INDEX and TYPE.
Let some table with identifiers like
Then, you can write
splitting and casting all parts.
If your database has compatibility level of 130 or higher then you can use the STRING_SPLIT function along with OFFSET FETCH clauses to get the specific item by index.
To get the item at index N (zero based), you can use the following code
To check the compatibility level of your database, execute this code:
I was looking for the solution on net and the below works for me. Ref.
And you call the function like this :
Yet another get n'th part of string by delimeter function:
and the usage:
which returns:
Try this:
Test it like this:
The following example uses a recursive CTE
Update 18.09.2013
Demo on SQLFiddle
I know it's an old Question, but i think some one can benefit from my solution.
SQL FIDDLE
Advantages:
Limitations:
Note: the solution can give sub-string up to to N.
To overcame the limitation we can use the following ref.
But again the above solution can't be use in a table (Actaully i wasn't able to use it).
Again i hope this solution can help some-one.
Update: In case of Records > 50000 it is not advisable to use
LOOPS
as it will degrade the PerformanceAlmost all the other answers split code are replacing the string being split which wastes CPU cycles and performs unnecessary memory allocations.
I cover a much better way to do a string split here: http://www.digitalruby.com/split-string-sql-server/
Here is the code:
You can split a string in SQL without needing a function:
If you need to support arbitrary strings (with xml special characters)
Pure set-based solution using
TVF
with recursiveCTE
. You canJOIN
andAPPLY
this function to any dataset.Usage:
Result:
Starting with SQL Server 2016 we string_split
A modern approach using STRING_SPLIT, requires SQL Server 2016 and above.
Result:
Now it is possible to get th nth element from the row number.
Aaron Bertrand's answer is great, but flawed. It doesn't accurately handle a space as a delimiter (as was the example in the original question) since the length function strips trailing spaces.
The following is his code, with a small adjustment to allow for a space delimiter:
Here is a function that will accomplish the question's goal of splitting a string and accessing item X:
Usage:
Result:
SIMPLE SOLUTION FOR PARSING FIRST AND LAST NAME
In my case (and in many others it seems...), I have a list of first and last names separated by a single space. This can be used directly inside a select statement to parse first and last name.
I know its late, but I recently had this requirement and came up with the below code. I don't have a choice to use User defined function. Hope this helps.
Well, mine isn't all that simpler, but here is the code I use to split a comma-delimited input variable into individual values, and put it into a table variable. I'm sure you could modify this slightly to split based on a space and then to do a basic SELECT query against that table variable to get your results.
The concept is pretty much the same. One other alternative is to leverage the .NET compatibility within SQL Server 2005 itself. You can essentially write yourself a simple method in .NET that would split the string and then expose that as a stored procedure/function.
This is something I did in order to get a specific token in a string. (Tested in MSSQL 2008)
First, creating the following functions: (found in: here
and
then you can use it like that:
which return 1111