HotDog's Blog

Hotdog (Robert Verpalen) about C# and vb.net

vbCity Blogs moved to:
http://cs.vbcity.com/blogs
  Home :: Syndication  :: Login

OctNovember 2009Dec
SMTWTFS
25262728293031
1234567
891011121314
15161718192021
22232425262728
293012345

Articles

Archives

Topics

CONTACT

Fun but useful linkies

General

VS 2005

Wolfenstein ET

First thing's first: the function :D

Code Copy

create
function Split (
@StringToSplit varchar(2048),
@Separator varchar(128))
returns table as return
with
indices as
(
select 0 S, 1 E
union all

select
E, charindex(@Separator, @StringToSplit, E) + len(@Separator)
from indices
where
E > S
)
select
substring(@StringToSplit,S,
case when E > len(@Separator) then e-s-len(@Separator) else len(@StringToSplit) - s + 1 end) String
,
S StartIndex        
from indices where S >0

 

Yeah, yeah, I know, such a function is an old topic and there are probably numerous solutions available, but I had the impression all were a bit outdated and created before the introduction of the CTE (Common Table Expression) in sql server 2005. Most examples either use a temporary table or return multiple result sets.
Ideal is the use of a function, but using a temporary table in it would prevent certain query optimizations that sql server would normally do for you (besides the small hit of creating a temptable). Granted, these days fast computers don't require that level of optimizing, but still, in heavy workloads every detail might matter ;)  In comes the 'newly' introduced CTE functionality. That might have been around for a couple of years, but I've never really used it until recenlty :$ Whatever the case, it makes a function such as split suddenly a lot shorter.
The function returns both the values (column name 'String' ) and the StartIndex. The Index might not be needed most of the time, but when joining, searching or selecting on the String, the column name is needed anyway, so the StartIndex won't be in the way, and it is there when it is needed. (As a small sidenote, in the case E > len(@Separator is used instead of E > S because the same optimizations that give the speed benefit, crashed the code on the substring() when using criteria on the string)

Some examples:

Code Copy
--simple split comma delimited string example
select
* from Split('aaa,b,cccc,dd,e,ffff,g' , ',')

--when the separator is not found, no problems either

select
* from Split('abcdefgh' , ',')

--empty values are returned too, the list would not be complete without them (for example when handling input file lines)

select
* from Split(',,a,,b,c,,,d' , ',')

--skipping the empty values would simply be using a criterium

select
* from Split(',,a,,b,c,,,d' , ',') where len(String) > 0

--of course, splitting with other (and longer) strings than a comma is supported too

select
* from Split('aaa->bb->cccc->d' , '->') where len(String) > 0

--just a final example with some query options combined

select
rtrim(ltrim(String)) from Split('from abc from abb from cdd from addd' , 'from')
where ltrim(String) like 'a%'
posted on Wednesday, June 04, 2008 1:21 AM

Feedback

# re: Split String Function T-SQL 7/18/2008 8:23 AM Randy
Try it with a longer string (with 300 elements). You will get a max receursion error and although there is a query hint to up the server default value from 100 (all the way up to 32K), it cannot be used in a function.

# re: Split String Function T-SQL 12/6/2008 5:10 PM va loan
I think i am following you.

# re: Split String Function T-SQL 6/5/2009 1:37 PM Ping Chan
The function is great. Just want to make it better.

1. use "datalength" replacing len(@Separator) so space could work as a separator as well

2. this function cannot work with any other select statement. Say, if I have a table "A" with a string column "col", it requires a cursor if I want to use this function. It would be good if there would be a way to use it with in a select statement.

# Extended Split String Function T-SQL 7/8/2009 3:41 AM Beni Gemperle
Thanks.

I extended your function with an additional RowNumber column. That's useful e.g. if you use a hierarchy like Category0Name/Category1Name/Category2Name/ etc.


CREATE FUNCTION Split (
@StringToSplit VARCHAR(2048),
@Separator VARCHAR(128)
)
RETURNS TABLE
AS
RETURN
WITH indices AS
(
SELECT
0 S,
1 E,
0 P
UNION ALL
SELECT
E,
CHARINDEX(@Separator, @StringToSplit, E) + LEN(@Separator),
0 P
FROM
indices
WHERE
E > S
)
SELECT
SUBSTRING(@StringToSplit, S, CASE WHEN E > LEN(@Separator) THEN e-s-len(@Separator) ELSE LEN(@StringToSplit) - s + 1 END) String,
S StartIndex,
ROW_NUMBER() OVER(ORDER BY P DESC) as WordPosition
FROM
indices
WHERE
S > 0

Post Feedback

Title:
Name:
Url:
Comments: 
Protected by Clearscreen.SharpHIPEnter the code you see: