3

I have strings in a database table like this:

Peter/Parker/Spiderman/Marvel
Bruce/Wayne/Batman/DC

Is there a way in SQL to extract specific values from a string e.g.

Name = MyColumn(0)
SurName = MyColumn(1)
Character = MyColumn(3)
Company = MyColumn(4)

Thanks

1
  • Will you have a unknown number of slashes / in your data? Or will it always have 3? Commented Nov 30, 2012 at 12:36

2 Answers 2

13

I'm assuming here that there are always exactly 4 parts.

If so, you could replace / with . and use the nice built in ParseName function. The only issue from your example is that it counts from the end, so you'd need to be careful about which part you want:

DECLARE @test VARCHAR(max);
SET @test = 'Peter/Parker/Spiderman/Marvel';
SET @test = Replace(@test, '/', '.');

SELECT Parsename(@test, 4),--returns Peter
       Parsename(@test, 3),--returns Parker
       Parsename(@test, 2),--returns Spiderman
       Parsename(@test, 1) --returns Marvel

If there are a variable number of parts, you'll need to find a string splitting function to do this for you, there isn't a good one built in. Many options can be found searching SO: https://stackoverflow.com/search?q=[sql+server]+string+split

Word of warning - if you try to use a number with PARSENAME other than 1-4, the result will always be NULL.

Sign up to request clarification or add additional context in comments.

Comments

5

If you know you will have exactly 4 columns, then you can also use this nested CTE version:

;with s1 (name, extra) as
(
  select left(data, charindex('/', data)-1), 
    substring(data, charindex('/', data) +1, len(data))
  from yourtable
),
s2 (name, surname, extra) as
(
  select name, 
    left(extra, charindex('/', extra)-1), 
    substring(extra, charindex('/', extra)+1, len(extra))
  from s1
),
s3 (name, surname, [character], company) as
(
  select name, 
    surname, 
    left(extra, charindex('/', extra)-1), 
    substring(extra, charindex('/', extra)+1, len(extra))
  from s2
)
select *
from s3;

See SQL Fiddle with Demo

The result is:

|  NAME | SURNAME | CHARACTER | COMPANY |
-----------------------------------------
| Peter |  Parker | Spiderman |  Marvel |
| Bruce |   Wayne |    Batman |      DC |

Or you can implement both a CTE that splits the data and then a PIVOT:

;with cte (item, data, colNum, rn) as
(
  select cast(left(data, charindex('/',data+'/')-1) as varchar(50)) item,
    stuff(data, 1, charindex('/',data+'/'), '') data,
    1 colNum,
    row_number() over(order by data) rn
  from yourtable
  union all
  select cast(left(data, charindex('/',data+'/')-1) as varchar(50)) ,
    stuff(data, 1, charindex('/',data+'/'), '') data,
    colNum+1, 
    rn
  from cte
  where data > ''
) 
select [1] as Name, 
  [2] as Surname, 
  [3] as [character], 
  [4] as company
from
(
  select item, colnum, rn
  from cte
) src
pivot
(
  max(item)
  for colnum in ([1], [2], [3], [4])
) piv

See SQL Fiddle with Demo

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.