How to parse unknown length string into different columns by using delimiter ('.').
declare osversion varchar(100)
set osversion = '6.2.9295'
SELECT [Part1] = LEFT(osversion,CHARINDEX('.',osversion) - 1),
[Part2] = SUBSTRING(osversion,CHARINDEX('.',osversion) + 1,
CHARINDEX('.',osversion,CHARINDEX('.',
osversion) + 1) - (CHARINDEX('.',osversion) + 1)),
[Part3] = SUBSTRING(osversion,CHARINDEX('.',
osversion,CHARINDEX('.',osversion) + 1) + 1,
DATALENGTH(osversion) - CHARINDEX('.',
osversion,CHARINDEX('.',osversion) + 1) -
CHARINDEX('.',REVERSE(osversion))),
from table1
Result:
Part1 Part2 Part3
6 2 9295
This result is for fixed length of string. I want to parse for an unknown length of string.
Like '86.52.929.695.22.1234'. Please help.
I purpose you to recreate the C#'s string.Split function in SQL. Here is the code
CREATE FUNCTION [dbo].[f_Split](
#String NVARCHAR (4000),
#Delimiter NVARCHAR (10)
)
RETURNS #T TABLE ([Value] NVARCHAR(4000))
BEGIN
DECLARE #NEXTSTRING NVARCHAR(4000)
DECLARE #POS INT,#DELIM_SIZE INT
DECLARE #NEXTPOS INT
SELECT
#NEXTSTRING = '',
#String = #String + #Delimiter,
#DELIM_SIZE = LEN(#Delimiter)
SET #POS = CHARINDEX(#Delimiter,#String)
SET #NEXTPOS = 1
WHILE (#POS <> 0)
BEGIN
SET #NEXTSTRING = SUBSTRING(#String,1,#POS - 1)
INSERT INTO #T ( [VALUE]) VALUES (#NEXTSTRING)
SET #String = SUBSTRING(#String,#POS +#DELIM_SIZE,LEN(#String))
SET #NEXTPOS = #POS
SET #POS = CHARINDEX(#Delimiter,#String)
END
RETURN
END
You can call the function like that
DECLARE #temp nvarchar(255); SELECT #temp = '86.52.929.695.22.1234';
SELECT * FROM dbo.f_Split(#temp,'.');
Here is the output :
Value
86
52
929
695
22
1234
Related
I am working on SQL Server (2005,2008 & 2012)
I wanna extract first five numbers from varchar column via using UDF
Input:
rrr123ddd4567ddd19828www2
123hhhsss124ss18762s
qq12349wsss12376ss
Output:
19828
18762
12349
My Trail is as following:
DECLARE
#myString VARCHAR(1000),
#temp VARCHAR(100),
#position INT,
#ExecuteInsert nvarchar (500),
#FirstChar bit
SET #myString = 'rrr123ddd4567ddd19828www2'
SET #position = 1
SET #FirstChar = 1
WHILE #position <= LEN(#myString)
BEGIN
IF (ISNUMERIC(SUBSTRING(#myString,#position,1))) = 1
BEGIN
SET #temp = isnull(#temp,'') + SUBSTRING(#myString,#position,1)
SET #FirstChar = 1
END
ELSE /* The char is alphabetical */
BEGIN
if (#FirstChar= 1)
BEGIN
SET #temp = isnull(#temp,'') + ','
SET #FirstChar = 0
END
END
SET #position = #position + 1
END
IF (RIGHT(#temp,1) <> ',')
BEGIN
SET #temp = #temp + ','
END
SELECT #temp = REPLACE(','+ #temp + ',',',,','')
SELECT #temp = Replace (#temp,',','''),(''')
Select #temp = '(''' + #temp + ''')'
Create table #temp
(
col1 varchar(100)
)
SET #ExecuteInsert = 'insert into #temp values ' + #temp
Execute sp_executesql #ExecuteInsert
select top 1 col1 from #temp
where LEN(col1) = 5
drop table #temp
-- Output >> 19828
The previous query is working well with string input , but I wanna using this code within UDF to could using it with columns.
if I used the previous query within UDF, the following error is raising:
Cannot access temporary tables from within a function.
EDIT
if I used Table variable , I get the next error:
Only functions and some extended stored procedures can be executed
from within a function.
any help will be greatly appreciated.
CREATE FUNCTION udfTest
(
-- Add the parameters for the function here
)
RETURNS int
AS
BEGIN
-- Declare the return variable here
DECLARE
#Result int,
#myString VARCHAR(1000),
#temp VARCHAR(100),
#position INT,
#ExecuteInsert nvarchar (500),
#FirstChar bit
SET #myString = 'rrr123ddd4567ddd19828www2'
SET #position = 1
SET #FirstChar = 1
WHILE #position <= LEN(#myString)
BEGIN
IF (ISNUMERIC(SUBSTRING(#myString,#position,1))) = 1
BEGIN
SET #temp = isnull(#temp,'') + SUBSTRING(#myString,#position,1)
SET #FirstChar = 1
END
ELSE /* The char is alphabetical */
BEGIN
if (#FirstChar= 1)
BEGIN
SET #temp = isnull(#temp,'') + ','
SET #FirstChar = 0
END
END
SET #position = #position + 1
END
IF (RIGHT(#temp,1) <> ',')
BEGIN
SET #temp = #temp + ','
END
SELECT #temp = REPLACE(','+ #temp + ',',',,','')
SELECT #temp = Replace (#temp,',','''),(''')
Select #temp = '(''' + #temp + ''')'
Declare #tempTable TABLE
(
col1 varchar(100)
)
insert into #tempTable SELECT #temp
select top 1 #Result=col1 from #tempTable
where LEN(col1) = 5
return #Result
END
GO
Here you are my answer of my question , hope helps others.
The objective is creating UDF function for using it with columns, not only fixed values.
The approach is using SplitString instead of sp_executesql
for splitting a comma separated string and loop it's values in table.
Demo:-
Create table DummyTable
( col1 varchar (100))
go
Insert into DummyTable values ('rrr123ddd4567ddd19828www2')
Insert into DummyTable values ('123hhhsss124ss18762s')
Insert into DummyTable values ('qq12349wsss12376ss')
go
/*
SplitString via Mudassar Khan
http://www.aspsnippets.com/Articles/Split-and-convert-Comma-Separated-Delimited-String-to-Table-in-SQL-Server.aspx
*/
Create FUNCTION SplitString
(
#Input NVARCHAR(MAX),
#Character CHAR(1)
)
RETURNS #Output TABLE (
Item NVARCHAR(1000)
)
AS
BEGIN
DECLARE #StartIndex INT, #EndIndex INT
SET #StartIndex = 1
IF SUBSTRING(#Input, LEN(#Input) - 1, LEN(#Input)) <> #Character
BEGIN
SET #Input = #Input + #Character
END
WHILE CHARINDEX(#Character, #Input) > 0
BEGIN
SET #EndIndex = CHARINDEX(#Character, #Input)
INSERT INTO #Output(Item)
SELECT SUBSTRING(#Input, #StartIndex, #EndIndex - 1)
SET #Input = SUBSTRING(#Input, #EndIndex + 1, LEN(#Input))
END
RETURN
END
GO
-------------------------------------
-------------------------------------
-------------------------------------
/*
My Own Function
*/
Create FUNCTION udfGetFirstFiveNumbers
(
#myString VARCHAR(1000)
)
RETURNS varchar(100)
AS
BEGIN
DECLARE
#temp VARCHAR(100),
#result Varchar (100),
#position INT,
#ExecuteInsert nvarchar (500),
#FirstChar bit
SET #position = 1
SET #FirstChar = 1
WHILE #position <= LEN(#myString)
BEGIN
IF (ISNUMERIC(SUBSTRING(#myString,#position,1))) = 1
BEGIN
SET #temp = isnull(#temp,'') + SUBSTRING(#myString,#position,1)
SET #FirstChar = 1
END
ELSE /* The char is alphabetical */
BEGIN
if (#FirstChar= 1)
BEGIN
SET #temp = isnull(#temp,'') + ','
SET #FirstChar = 0
END
END
SET #position = #position + 1
END
IF (RIGHT(#temp,1) <> ',')
BEGIN
SET #temp = #temp + ','
END
SELECT #temp = REPLACE(','+ #temp + ',',',,','')
SELECT #result = Item
FROM dbo.SplitString(#temp, ',')
where len(Item) = 5
return #result
END
GO
-- Test
select col1, dbo.udfGetFirstFiveNumbers(col1) as result
from DummyTable
Result:-
I wrote a sql server function which returns substring before the Nth occurence of character.
For example,
SELECT dbo.fn_getFirstNthSentence('.', 'hello world.It.is.raining.today', 3)
returns 'hello world.It.Is.' as a result.
The function I wrote looks dirty and slow so I want to optimize it.
Any advice to make it clean is appreciated.
Thank you.
CREATE FUNCTION fn_getFirstNthSentence
(
#TargetStr VARCHAR(MAX) ,
#SearchedStr VARCHAR(8000) ,
#Occurrence INT
)
RETURNS varchar(MAX)
AS
BEGIN
DECLARE #pos INT ,
#counter INT ,
#ret INT;
SET #pos = CHARINDEX(#TargetStr, #SearchedStr);
IF ( #pos = 0 )
RETURN #SearchedStr
SET #counter = 1;
IF #Occurrence = 1
SET #ret = #pos;
ELSE
BEGIN
WHILE ( #counter < #Occurrence )
BEGIN
IF(LEN(#SearchedStr) < #pos + 1)
RETURN #SearchedStr
SELECT #ret = CHARINDEX(#TargetStr, #SearchedStr,
#pos + 1);
IF(#ret = 0)
RETURN #SearchedStr
SET #counter = #counter + 1;
SET #pos = #ret;
END;
END;
RETURN LEFT(#SearchedStr, #ret)
END;
Here is yet another option using a delimited string splitter. The XML method already posted is a good one but this approach does not require a table variable.
This is created as an inline table valued function which should keep the performance really fast.
create function fn_getFirstNthSentence
(
#SearchedStr varchar(100)
, #Occurrence int
, #Delimiter char(1)
) returns table as return
with ParsedValues as
(
select Item
, ItemNumber
from dbo.DelimitedSplit8K(#SearchedStr, #Delimiter)
where ItemNumber <= #Occurrence
)
select top 1 ResultString = STUFF(
(
select #Delimiter + Item
from ParsedValues
order by ItemNumber
for xml path('')), 1,1, '') + #Delimiter
from ParsedValues
This is also using a splitter created by Jeff Moden. It has one feature that none of the other splitter have...a column to indicate which position the value came from. You can find his article an ensuing discussion here. http://www.sqlservercentral.com/articles/Tally+Table/72993/
Then if you want to execute it you can do this quite simply.
declare #String varchar(100) = 'hello world.It.is.raining.today.'
, #Num int = 3
, #Delimiter char(1) = '.'
;
select *
from fn_getFirstNthSentence(#String, #Num, #Delimiter)
If you don't like Jeff Moden's splitter you can find several other options here. http://sqlperformance.com/2012/07/t-sql-queries/split-strings I don't use Moden's for everything but when you need to keep the parsed values in order it is awesome.
--EDIT--
Here is how you could modify this to become a scalar function instead of an inline table valued function. My preference would be to keep the itvf as they are faster and more flexible.
create function fn_getFirstNthSentenceScalar
(
#SearchedStr varchar(100) = 'hello world.It.is.raining.today.this is after 5'
, #Occurrence int = 5
, #Delimiter char(1) = '.'
) returns varchar(max) as begin
declare #RetVal varchar(max);
with ParsedValues as
(
select Item
, ItemNumber
from dbo.DelimitedSplit8K(#SearchedStr, #Delimiter)
where ItemNumber <= #Occurrence
)
select top 1 #RetVal = STUFF(
(
select #Delimiter + Item
from ParsedValues
order by ItemNumber
for xml path('')), 1,1, '') + #Delimiter
from ParsedValues;
return #RetVal
end
--I find these functions to be a mine-field, and at the risk of stepping on a mine I've tried some simplifications - maybe a microscopic improvement in performance
alter FUNCTION fn_getFirstNthSentence
(
#TargetStr VARCHAR(MAX) ,
#SearchedStr VARCHAR(8000) ,
#Occurrence INT
)
RETURNS varchar(MAX)
AS
BEGIN
DECLARE #pos INT ,
#counter INT ;
IF #Occurrence < 1
RETURN NULL;
SELECT #counter = 0, #POS = 1;
WHILE (#counter < #Occurrence AND #POS > 0)
BEGIN
SELECT #POS = CHARINDEX(#TargetStr, #SearchedStr,
#pos + 1);
IF #POS > 0
SET #counter = #counter + 1;
END;
RETURN CASE WHEN #POS > 0 THEN
LEFT(#SearchedStr, #POS)
ELSE
#SearchedStr
END;
END;
Another option is via XML
I can't see your benchmarks, but it is certainly far less code. An added option could be Find the 3rd through 5th occurrence by adding a parameter and changing the Where Seq<=#FindPos to Where Seq Between range1 and range2.
Declare #FindPos int = 3
Declare #String varchar(max) = 'hello world.It.is.raining.today'
Declare #Delim varchar(10) = '.'
Declare #XML xml,#RetVal varchar(max) = ''
Set #XML = Cast('<x>' + Replace(#String,#Delim,'</x><x>')+'</x>' as XML)
Declare #Table table (Seq int identity(1,1),String varchar(max))
Insert Into #Table Select ltrim(rtrim(String.value('.', 'varchar(max)')))+#Delim as value FROM #XML.nodes('x') as T(String)
Select #RetVal=#RetVal + String from #Table Where Seq<=#FindPos Order By Seq
Select #RetVal
Returns
hello world.It.is.
EDIT: If it helps, below is my generic parsing function which returns a
normalized table...
CREATE FUNCTION [dbo].[udf-Str-Parse] (#String varchar(max),#Delimeter varchar(10))
--Usage: Select * from [dbo].[udf-Str-Parse]('Dog,Cat,House,Car',',')
-- Select * from [dbo].[udf-Str-Parse]('John Cappelletti was here',' ')
-- Select * from [dbo].[udf-Str-Parse]('id26,id46|id658,id967','|')
-- Select * from [dbo].[udf-Str-Parse]('hello world. It. is. . raining.today','.')
Returns #ReturnTable Table (Key_PS int IDENTITY(1,1), Key_Value varchar(max))
As
Begin
Declare #XML xml;Set #XML = Cast('<x>' + Replace(#String,#Delimeter,'</x><x>')+'</x>' as XML)
Insert Into #ReturnTable Select Key_Value = ltrim(rtrim(String.value('.', 'varchar(max)'))) FROM #XML.nodes('x') as T(String)
Return
End
So for example:
Select * from [dbo].[udf-Str-Parse]('hello world.It.is.raining.today','.')
Returns
Key_PS Key_Value
1 hello world
2 It
3 is
4 raining
5 today
I have a set of data for example:
Part no Custom Format
1128005 \Machines\3D\PartNo(2)\PartNo(4)xx\PartNo(7)
11.88.006 \Machines\3D\PartNo(2)\PartNo+3(2)xx\PartNo+6(3)
I want to replace the variable set in the custom format define in it. The result i am looking for is
For Part no
1128005
the result is
\Machines\3D\11\1128xx\1128005
11.88.006
\Machines\3D\11\88xx\006
Any ideas?
Thanks
Regards
If my understanding is correct, below script should be what you want? But because it processes row by row, it can be very slow when dealing with millions of rows.
--declare #input varchar(50) = '11.88.006', #pattern varchar(255) = '\Machines\3D\PartNo(2)\PartNo+3(2)xx\PartNo+6(3)'
declare #input varchar(50) = '1128005', #pattern varchar(255) = '\Machines\3D\PartNo(2)\PartNo(4)xx\PartNo(7)'
declare #tblPattern table (tmpKey int identity(1,1), result varchar(50), Position varchar(50), SkipCnt int, CharLength int, Sufix varchar(50))
declare #i int = 1, #output varchar(max) = '\Machines\3D\'
Declare #PatternXml XML
Set #PatternXml = N'<root><r>' + REPLACE(replace(#pattern, '\Machines\3D\', ''), '\', '</r><r>') + '</r></root>'
insert into #tblPattern(result)
select r.value('.', 'VARCHAR(MAX)') as t
from #PatternXml.nodes('//root//r') as records(r)
update #tblPattern set Position = REPLACE(result, 'PartNo', '')
, SkipCnt = CASE WHEN CHARINDEX('+', result, 1) > 0 THEN SUBSTRING(result, CHARINDEX('+', result, 1) + 1, CHARINDEX('(', result, 1) - CHARINDEX('+', result, 1) - 1) ELSE 0 END
, CharLength = SUBSTRING(result, CHARINDEX('(', result, 1) + 1, CHARINDEX(')', result, 1) - CHARINDEX('(', result, 1) - 1 )
, Sufix = SUBSTRING(result, CHARINDEX(')', result, 1) + 1, LEN(result))
while #i <= 3
begin
select #output += SUBSTRING(#input, 1 + SkipCnt, CharLength) + Sufix + '\'
from #tblPattern
where tmpKey = #i
set #i += 1
end
select #output = STUFF(#output, len(#output), 1, '')
select #output
How do I replace the characters ~!##$%^&*()_+}{][ in a nvarchar (or varchar) field with a - using TSQL?
you can create user define function for that as given below
CREATE FUNCTION udf_ReplaceSpecialChar
(
#inputString VARCHAR(1000)
)
RETURNS VARCHAR(1000)
AS
BEGIN
DECLARE #outputString VARCHAR(1000),
#LENGTH INT,
#index INT,
#char CHAR(1)
SELECT #LENGTH = LEN(#inputString),
#index = 1
WHILE(#index <= #LENGTH)
BEGIN
SET #char = SUBSTRING(#inputString, #index, 1)
IF((ASCII(#char) NOT BETWEEN 65 AND 90) AND (ASCII(#char) NOT BETWEEN 97 AND 122) AND (ASCII(#char) NOT BETWEEN 48 AND 57))
BEGIN
SELECT #inputString = REPLACE(#inputString, #char, '-')
END
SET #index = #index + 1
END
SET #outputString = #inputString
RETURN #outputString
END
SELECT dbo.udf_ReplaceSpecialChar('This()*& is%%#Sample**.>String')
or you should replace each character with '-'
Like
SELECT REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE('This()*& is%%#Sample**.>String', ' ', '-'), '*', '-'), '#', '-'), '&', '-'), '(', '-'), ')', '-'), '.', '-'), '>', '-'), '%', '-')
You can use REPLACE function. If it doesn't work in some cases, please give us examples.
May be this code is that you are searching for:
-- Author: Christian d'Heureuse, www.source-code.biz
create function dbo.RemoveSpecialChars (#s varchar(256)) returns varchar(256)
with schemabinding
begin
if #s is null
return null
declare #s2 varchar(256)
set #s2 = ''
declare #l int
set #l = len(#s)
declare #p int
set #p = 1
while #p <= #l begin
declare #c int
set #c = ascii(substring(#s, #p, 1))
if #c between 48 and 57 or #c between 65 and 90 or #c between 97 and 122
set #s2 = #s2 + char(#c)
set #p = #p + 1
end
if len(#s2) = 0
return null
return #s2
end
It removes all characters except 0-9, a-z and A-Z. This function uses ASCII codes of characters to determine this ones which must be removed.
--another one variant
----------------------------------------------------------------------------------------
--better to keep such table in server, very usefull table, especially with indexes
DECLARE #Tally TABLE ( N INT )
DECLARE #i AS INT = 1
WHILE #i != 1000
BEGIN
INSERT INTO #Tally
( N )
VALUES ( #i )
SET #i = #i + 1
END
----------------------------------------------------------------------------------------
DECLARE #String AS VARCHAR(1000) = 'This()*& is%%# **.>another one //&^&*$variant'
----------------------------------------------------------------------------------------
--using #tally - split, using like - remove not required, 'for xml ...' - combine into string
SELECT REPLACE(( SELECT LEFT(SUBSTRING(#String, n, 1000), 1)
FROM #Tally AS T
WHERE SUBSTRING(#String, n, 1000) != ''
AND LEFT(SUBSTRING(#String, n, 1000), 1) LIKE '[A-Za-z0-9 ]'
FOR
XML PATH('')
), ' ', ' ')
--another one variant
------------------------------------------------------------------------------------
--better to keep such table in server, very usefull table, especially with indexes
DECLARE #Tally TABLE ( N INT )
DECLARE #i AS INT = 1
WHILE #i != 1000
BEGIN
INSERT INTO #Tally
( N )
VALUES ( #i )
SET #i = #i + 1
END
------------------------------------------------------------------------------------
DECLARE #String VARCHAR(500) ,
#B VARCHAR(500) = ''
SET #String = 'This()*& is%%# **.>another one //&^&*$variant'
SELECT #B = #B + SUBSTRING(#String, t.N, 1)
FROM #Tally t
WHERE t.N <= DATALENGTH(#String)
AND PATINDEX('[A-Za-z0-9 ]', SUBSTRING(#String, t.N, 1)) > 0
SELECT #B
--------------------------------------------------------------------------------
if you wish use this method like a function then:
Create Tally table with one field PRIMARY KEY (1000 rows, starting from 1 with step 1)
Use code below to create function
Table Tally will be very useful for the split sting, clean string etc., currently this is
the best way to use instead fetch, xml and etc.
--------------------------------------------------------------------------------
CREATE FUNCTION [dbo].[StringClean](
#A VARCHAR(500))
RETURNS VARCHAR(500)
AS
BEGIN
DECLARE #B VARCHAR(500)
SET #B = ''
SELECT #B = #B + SUBSTRING(#A, t.N, 1)
FROM dbo.Tally t
WHERE t.N <= DATALENGTH(#A)
AND PATINDEX('[A-Za-z0-9 ]', SUBSTRING(#A, t.N, 1)) > 0
RETURN #B
END
-------------------------------------------------------------------------------
SELECT dbo.StringClean('This()*& is%%# **.>another one //&^&*$variant')
-------------------------------------------------------------------------------
DECLARE #Tally TABLE ( N INT )
DECLARE #i AS INT = 1
WHILE #i != 1000
BEGIN
INSERT INTO #Tally (N) VALUES (#i)
SET #i = #i + 1
END
--------------------------------------------------------------
DECLARE #String VARCHAR(500)
DECLARE #B VARCHAR(500) = ''
DECLARE #ReplacedChars VARCHAR(50) = '~!##$%^&*()_+}{][<>/.'
SET #String = 'This()*& is%%# **.>another one //&^&*$variant'
SELECT #B = #B + CASE WHEN CHARINDEX(SUBSTRING(#String, t.N, 1), #ReplacedChars) > 0 THEN '-'
ELSE SUBSTRING(#String, t.N, 1) END
FROM #Tally t
WHERE t.N <= DATALENGTH(#String)
SELECT #B
I want to split string 'GPIN-KH2-COH-24042014-02' by '-' in sqlserver 2008 and want to save in separate variables. How can I achieve this? Please help me in this regard.
Now I am using below function and pass it ('GPIN-KH2-COH-24042014-02', '-')
Create FUNCTION [dbo].[fnSplit]
(
#strInputList NVARCHAR (MAX), -- List of Delimited Items
#strDelimiter NVARCHAR (11) = ',' -- Delimiter that Separates Items
)
RETURNS #tblList TABLE (strItem NVARCHAR(250))
BEGIN
DECLARE #strItem NVARCHAR(MAX)
WHILE CHARINDEX(#strDelimiter,#strInputList,0) <> 0
BEGIN
SELECT
#strItem = RTRIM(LTRIM( (SUBSTRING (#strInputList, 1, CHARINDEX (#strDelimiter, #strInputList, 0) -1)))),
#strInputList = RTRIM(LTRIM( (SUBSTRING (#strInputList, CHARINDEX (#strDelimiter, #strInputList, 0) + LEN (#strDelimiter), LEN (#strInputList)))))
IF LEN(#strItem) > 0
INSERT INTO #tblList SELECT #strItem
END
IF LEN(#strInputList) > 0
INSERT INTO #tblList SELECT #strInputList
RETURN
END
Result:
strItem
GPIN
KH2
COH
24042014
02
When I was delimeter and string it return result in that table format as shown above. But I want to get last two rows. How can I get this?
CRETAE function and pass your string and Delimiter as parameter
FUNCTION:
CREATE FUNCTION [dbo].[Split](#String varchar(8000), #Delimiter char(1))
returns #temptable TABLE (items varchar(8000))
as
begin
declare #idx int
declare #slice varchar(8000)
select #idx = 1
if len(#String)<1 or #String is null return
while #idx!= 0
begin
set #idx = charindex(#Delimiter,#String)
if #idx!=0
set #slice = left(#String,#idx - 1)
else
set #slice = #String
if(len(#slice)>0)
insert into #temptable(Items) values(#slice)
set #String = right(#String,len(#String) - #idx)
if len(#String) = 0 break
end
return
end
And then call the function and use the values as you want
DECLARE #A VARCHAR (100)= 'GPIN-KH2-COH-24042014-02'
SELECT items
INTO #STRINGS
FROM dbo.split(#A,'-')
select * from #STRINGS
Use this function, download from here
usage
SELECT DBO.fnString_DelimeterIndex(N'GPIN-KH2-COH-24042014-02','-',1)
SELECT DBO.fnString_DelimeterIndex(N'GPIN-KH2-COH-24042014-02','-',2)
SELECT DBO.fnString_DelimeterIndex(N'GPIN-KH2-COH-24042014-02','-',3)
function
ALTER FUNCTION [dbo].[fnString_DelimeterIndex]
(
#Text NVARCHAR(4000),
#Delimiter CHAR,
#Section SMALLINT
)
RETURNS NVARCHAR(4000)
AS
BEGIN
DECLARE #NextPos SMALLINT,
#LastPos SMALLINT,
#Found SMALLINT,
#REVERSE BIT
IF #Section < 0
SELECT #Text = REVERSE(#Text)--, #Section=1,#REVERSE=1
SELECT #NextPos = CHARINDEX(#Delimiter, #Text, 1),
#LastPos = 0,
#Found = 1
WHILE #NextPos > 0 AND ABS(#Section) <> #Found
SELECT #LastPos = #NextPos,
#NextPos = CHARINDEX(#Delimiter, #Text, #NextPos + 1),
#Found = #Found + 1
RETURN CASE
WHEN #Found <> ABS(#Section) OR #Section = 0 THEN NULL
--WHEN #REVERSE =1 THEN
WHEN #Section > 0 THEN SUBSTRING(#Text, #LastPos + 1, CASE WHEN #NextPos = 0 THEN DATALENGTH(#Text) - #LastPos ELSE #NextPos - #LastPos - 1 END)
ELSE REVERSE(SUBSTRING(#Text, #LastPos + 1, CASE WHEN #NextPos = 0 THEN DATALENGTH(#Text) - #LastPos ELSE #NextPos - #LastPos - 1 END))
END
END
Here is a fancy way of solving it:
You need a function to split it first:
create function [dbo].[f_specialsplit]
(
#param nvarchar(max),
#delimiter char(1)
)
returns #t table (val nvarchar(max), rn varchar(9))
as
begin
set #param += #delimiter
;with a as
(
select cast(1 as bigint) f, charindex(#delimiter, #param) t where #param is not null
union all
select t + 1, charindex(#delimiter, #param, t + 1)
from a
where charindex(#delimiter, #param, t + 1) > 0
)
insert #t
select substring(#param, f, t - f), row_number() over (order by (select 1)) from a
option (maxrecursion 0)
return
end
Trick is now to pivot the data into the variables:
DECLARE #str varchar(100) = 'GPIN-KH2-COH-24042014-02'
DECLARE #s1 varchar(100),#s2 varchar(100),#s3 varchar(100),#s4 varchar(100),#s5 varchar(100)
SELECT #s1=[1],#s2=[2],#s3=[3],#s4=[4],#s5=[5]
FROM f_specialsplit(#str,'-')
PIVOT
(min([val])
FOR rn
in([1],[2],[3],[4],[5])
)AS p
SELECT #s1,#s2,#s3,#s4,#s5
Result:
GPIN KH2 COH 24042014 02