Split string by comma in SQL Server 2008 - sql

There are two strings a and b
The a string contains comma. I would like to split the a string by comma, then go through every element .
IF the b string contains any element which split by comma will return 0
(e.g: a = "4,6,8" ; b = "R3799514" because the b string contains 4 so return 0)
How to achieve this with a stored procedure? Thanks in advance!
I have seen a split 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
select top 10 * from dbo.split('Chennai,Bangalore,Mumbai',',')

Following will work -
DECLARE #A VARCHAR (100)= '4,5,6'
DECLARE #B VARCHAR (100)= 'RXXXXXX'
DECLARE #RETURN_VALUE BIT = 1 --DEFAULT 1
SELECT items
INTO #STRINGS
FROM dbo.split(#A,',')
IF EXISTS(SELECT 1 FROM #STRINGS S WHERE CHARINDEX(items, #B) > 0)
SET #RETURN_VALUE = 0
PRINT #RETURN_VALUE
DROP TABLE #STRINGS
You can also use CONTAINS instead of CHARINDEX -
IF EXISTS(SELECT 1 FROM #STRINGS S WHERE CONTAINS(items, #B))
SET #RETURN_VALUE = 0

Related

SSRS Report: get parameter data value and store it into variable in dataset

I have multi-valued parameter in my Report named #Animal which has ('Cat', 'Dog', 'Mouse').
inside dataset i need to get 'Cat', Dog', 'Mouse' and store it into #AnimalName table variable.
"Hard-Coded" way would be:
DECLARE #AnimalName TABLE (Name nvarchar (10))
INSERT INTO #AnimalName SELECT ('Cat');
INSERT INTO #AnimalName SELECT ('Dog');
INSERT INTO #AnimalName SELECT ('Mouse');
I know that I can use #Animal directly inside my dataset, the reason I'm doing this is because I'm trying to improve my report's performance. Many multi-valued parameters will make the report runs forever.
Does any one know how(the syntax) to get #Animal data values and stored it into a table variables #AnimalName inside dataset?
Thanks heaps!
Pass the comma delimited string into your stored procedure and in your stored proc use a table valued function to convert you multi-valued parameter into a table.
CREATE PROC GetAllAnimals
#AnimalList nvarchar(max)
AS
DECLARE #Animals TABLE (Animal nvarchar(10))
INSERT INTO #Animals SELECT * FROM dbo.fnGetValueListFromMultiSelect(#AnimalList)
and then use the #Animals table to inner join in your query
Functions declared below.
For Integer (or ID) values
CREATE FUNCTION [dbo].[fnGetIdListFromMultiSelect](#String nvarchar(MAX))
RETURNS #Results TABLE ([Id] int)
AS
BEGIN
DECLARE #Delimiter CHAR(1)
DECLARE #INDEX INT
DECLARE #SLICE nvarchar(4000)
IF #String IS NULL RETURN
SET #Delimiter = ','
SET #INDEX = 1
WHILE #INDEX !=0
BEGIN
-- GET THE INDEX OF THE FIRST OCCURENCE OF THE SPLIT CHARACTER
SELECT #INDEX = CHARINDEX(#Delimiter,#STRING)
-- NOW PUSH EVERYTHING TO THE LEFT OF IT INTO THE SLICE VARIABLE
IF #INDEX !=0
BEGIN
SELECT #SLICE = LEFT(#STRING,#INDEX - 1)
-- CHOP THE ITEM REMOVED OFF THE MAIN STRING
SELECT #STRING = RIGHT(#STRING,LEN(#STRING) - #INDEX)
END
ELSE
SELECT #SLICE = #STRING
-- PUT THE ITEM INTO THE RESULTS SET
INSERT INTO #Results([Id]) VALUES(CAST(#SLICE AS INT))
-- BREAK OUT IF WE ARE DONE
IF LEN(#STRING) = 0 BREAK
END
RETURN
END
For string values
CREATE FUNCTION [dbo].[fnGetValueListFromMultiSelect](#String nvarchar(MAX))
RETURNS #Results TABLE ([Item] nvarchar(128) Primary Key)
AS
BEGIN
DECLARE #Delimiter CHAR(1)
DECLARE #INDEX INT
DECLARE #SLICE nvarchar(4000)
SET #Delimiter = ','
SET #INDEX = 1
WHILE #INDEX !=0
BEGIN
-- GET THE INDEX OF THE FIRST OCCURENCE OF THE SPLIT CHARACTER
SELECT #INDEX = CHARINDEX(#Delimiter,#STRING)
-- NOW PUSH EVERYTHING TO THE LEFT OF IT INTO THE SLICE VARIABLE
IF #INDEX !=0
BEGIN
SELECT #SLICE = LEFT(#STRING,#INDEX - 1)
-- CHOP THE ITEM REMOVED OFF THE MAIN STRING
SELECT #STRING = RIGHT(#STRING,LEN(#STRING) - #INDEX)
END
ELSE
SELECT #SLICE = #STRING
-- PUT THE ITEM INTO THE RESULTS SET
INSERT INTO #Results([Item]) VALUES(#SLICE)
-- BREAK OUT IF WE ARE DONE
IF LEN(#STRING) = 0 BREAK
END
RETURN
END

Getting id values from a column and then get value from another table

I have a column value separated by comma as
GoalTag:All Tags,TaskTag:All Tags,GoalId:All,TaskId:All,MaxGoal:5,MaxTask:5
As you can see I have 6 values separated by comma, so when I do split the first value will be
GoalTag:All Tags
How I do this (get the values seperated by comma is) by calling a table valued function
Select * from dbo.CustomSplit((SELECT FilterNames FROM TblUserFilterView where UserId = 325 AND Entity = 'Dashboard'),',')
The definition for dbo.CustomSplit looks like
ALTER FUNCTION [dbo].[CustomSplit](#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
Now what I need to do is, I need to get the value after the ":" i.e. "All Tags" it may be some id for some other records let's say it may be "142". I need to get this Id and then get the corresponding value from the table.
How can I do this?
Try this:
SELECT Substring(s.items, 1 + Charindex ( ':', s.items),
Len(s.items) - Charindex (':',
s.items))
FROM (SELECT *
FROM dbo.Customsplit((SELECT filternames
FROM tbluserfilterview
WHERE userid = 325
AND entity = 'Dashboard'), ',')) AS s
You may create another function:
CREATE FUNCTION [dbo].[Customsplit2](#string VARCHAR(8000),
#Delimiter CHAR(1))
returns VARCHAR(4000)
AS
BEGIN
DECLARE #result NVARCHAR(4000)
SELECT #result = Substring(#string, 1 + Charindex ( #Delimiter, #string),
Len(#string) - Charindex (#Delimiter,
#string)
)
RETURN #result
END
And use it like:
SELECT [dbo].Customsplit2(s.items, ':') AS Tag
FROM (SELECT *
FROM dbo.Customsplit((SELECT filternames
FROM tbluserfilterview
WHERE userid = 325
AND entity = 'Dashboard'), ',')) AS s

Insert values into table after splitting the string

I want to insert values into employee table.
And those values are in string format ~ separated
E.g: AA~B~123
I am splitting it using following function
CREATE FUNCTION [db_owner].[FN_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
Now I get Output as
SELECT * FROM db_owner.FN_Split('AA~B~123','~')
Output
items
______
AA
B
123
Now I am stuck here
How can I insert above values in employee table???
like
insert into employee (name,add,phone)
values('AA','B','123');
Please guide.
Tried this but not working
insert into employee
SELECT * FROM db_owner.FN_Split('AA~BB~CC','~')
ERROR
Msg 213, Level 16, State 1, Line 1
Column name or number of supplied values does not match table definition.
You are using a string split function that returns your items as rows. You need a function that return them as columns instead.
Or you can do it directly in the query. Perhaps something like this.
declare #S varchar(10) = 'AA~B~123'
select left(#S, T1.Pos - 1) as Col1,
substring(#S, T1.Pos+1, T2.Pos-T1.Pos-1) as Col2,
substring(#S, T2.Pos+1, len(#S)-T2.Pos) as Col3
from (select charindex('~', #S)) as T1(Pos)
cross apply (select charindex('~', #S, T1.Pos+1)) as T2(Pos)
Result:
Col1 Col2 Col3
---------- ---------- ----------
AA B 123
Here is a version that works in SQL Server 2000
declare #S varchar(10)
set #S = 'AA~B~123'
select left(#S, T.Pos1 - 1) as Col1,
substring(#S, T.Pos1+1, T.Pos2-T.Pos1-1) as Col2,
substring(#S, T.Pos2+1, len(#S)-T.Pos2) as Col3
from (select T.Pos1,
charindex('~', #S, T.Pos1+1) as Pos2
from (select charindex('~', #S) as Pos1) as T
) as T
if you could add a small counter into the stored procedure like this then life would be easier:
CREATE FUNCTION [db_owner].[FN_Split] (#String varchar(8000), #Delimiter char(1))
returns #temptable TABLE (orderId int,items varchar(8000))
as
begin
declare #idx int
declare #slice varchar(8000)
declare #orderId int = 0 --<added a counter
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(orderId, Items) values(#orderId, #slice)
set #orderId = #orderId+1 --<increment the counter
set #String = right(#String,len(#String) - #idx)
if len(#String) = 0 break
end
return
end
Your subsequent query could be something like the following:
DECLARE #name varchar(50) = (SELECT items FROM db_owner.FN_Split('AA~BB~CC','~') where orderId = 0)
DECLARE #add varchar(50) = (SELECT items FROM db_owner.FN_Split('AA~BB~CC','~') where orderId = 1)
DECLARE #phone varchar(50) = (SELECT items FROM db_owner.FN_Split('AA~BB~CC','~') where orderId = 2)
insert into employee
(
name,
add,
phone
)
values
(
#name,
#add,
#phone
)
But have you tried changing the procedure so that it outputs the data in a horizontal format rather than the vertical output that you currently have?
Please try this query:
Insert into employee(col1,col2,col3)
select substring_index('AA~B~123','~',1) as col1,substring_index(substring_index('AA~B~123','~',-2),'~',1) as col2,
substring_index(substring_index('AA~B~123','~',-1),'~',1) as col3

How to modify the function to get output as three columns?

I got this function to split string but it's giving the spited string in one column I want like below.
How can i modify the function to get the output like below.
I found this function on google.
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
SELECT * from dbo.Split('hello hi guys',' ');
items
--------
hello
hi
guys
I want like this
col1 col2 col3
_____ _______ _______
hello hi guys
If you can guarantee that no XML characters will be passed into #String, try the following...
UPDATED to make "safer" against XML characters (although it still will fail if ]]> is contained...
CREATE FUNCTION dbo.Split(#String varchar(8000), #Delimiter char(1))
returns #temptable TABLE (col1 varchar(8000), col2 varchar(8000), col3 varchar(8000))
as
begin
declare #xml xml
set #xml = '<data><col><![CDATA[' +
replace(#String,#Delimiter,']]></col><col><![CDATA[') +
']]></col></data>'
insert into #temptable (col1, col2, col3)
select parts.value('col[1]','varchar(8000)'),
parts.value('col[2]','varchar(8000)'),
parts.value('col[3]','varchar(8000)')
from #xml.nodes('/data') as parts(parts)
return
end

How to split a string in T-SQL?

I have a varchar #a='a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p', which has | delimited values. I want to split this variable in a array or a table.
How can I do this?
Use a table valued function like this,
CREATE FUNCTION Splitfn(#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 get your variable and use this function like this,
SELECT i.items FROM dbo.Splitfn(#a,'|') AS i
In general, this is such a common question here
I'll give the common answer: Arrays and Lists in SQL Server 2005 and Beyond by Erland Sommarskog
I'd recommend a table of numbers, not a loop, for general use.
Try this one:
declare #a varchar(10)
set #a = 'a|b|c|'
while len(#a) > 1
begin
insert into #temp
select substring(#a,1,patindex('%|%',#a)-1);
set #a = substring(#a,patindex('%|%',#a)+1,len(#a))
end;
Here's an alternative XML based solution. It seems to have a similar performance as the Splitfn() solution.
This converts varchar a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p into XML <a>a</a><a>b</a><a>c</a><a>d</a><a>e</a><a>f</a><a>g</a><a>h</a><a>i</a><a>j</a><a>k</a><a>l</a><a>m</a><a>n</a><a>o</a><a>p</a> and extracts the value from each XML <a> node.
declare #a varchar(max);
set #a = 'a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p';
declare #xml xml;
set #xml
= '<a>'+replace(replace(replace(#a,'&','&'),'<','<'),'|','</a><a>')+'</a>';
SELECT x.n.value('.','VARCHAR(1)') AS singleValue
FROM #xml.nodes('/a') AS x(n)
;