Insert values into table after splitting the string - sql

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

Related

SQL Split Function and Ordering Issue?

I have the following Split function,
ALTER FUNCTION [dbo].[Split](#String varchar(8000), #Delimiter char(1))
returns #temptable TABLE (items varchar(8000))
as
begin
set #String = RTRIM(LTRIM(#String))
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
When I write,
SELECT Items
FROM Split('around the home,clean and protect,soaps and air fresheners,air fresheners',',')
This will give me,
air fresheners
around the home
clean and protect
soaps and air fresheners
I need to maintain the order.
A simpler function:
CREATE FUNCTION dbo.SplitStrings_Ordered
(
#List nvarchar(MAX),
#Delimiter nvarchar(255)
)
RETURNS TABLE
AS
RETURN
(
SELECT [Index] = CHARINDEX(#Delimiter, #List + #Delimiter, Number),
Item = SUBSTRING(#List, Number, CHARINDEX(#Delimiter,
#List + #Delimiter, Number) - Number)
FROM
(
SELECT ROW_NUMBER() OVER (ORDER BY [object_id]) FROM sys.all_objects
) AS n(Number)
WHERE Number <= CONVERT(INT, LEN(#List))
AND SUBSTRING(#Delimiter + #List, Number, LEN(#Delimiter)) = #Delimiter
);
GO
Sample usage:
DECLARE #s nvarchar(MAX) = N',around the home,clean and protect,soaps and air'
+ ' fresheners,air fresheners';
SELECT Item FROM dbo.SplitStrings_Ordered(#s, N',') ORDER BY [Index];
Or to return orders from a table ordered by input:
SELECT o.OrderID
FROM dbo.Orders AS o
INNER JOIN dbo.SplitStrings_Ordered('123,789,456') AS f
ON o.OrderID = CONVERT(int, f.Item)
ORDER BY f.[Index];
Your function will need to set an order column (seq in this sample):
ALTER FUNCTION [dbo].[Split](#String varchar(8000), #Delimiter char(1))
returns #temptable TABLE (seq int, items varchar(8000))
as
begin
set #String = RTRIM(LTRIM(#String))
declare #idx int
declare #seq int
declare #slice varchar(8000)
set #seq=1
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)
begin
set #seq = #seq + 1
insert into #temptable(seq, Items) values(#seq,#slice)
end
set #String = right(#String,len(#String) - #idx)
if len(#String) = 0 break
end
return
end
GO
SELECT * FROM Split('around the home,clean and protect,soaps and air fresheners,air fresheners',',') order by seq
declare #Version nvarchar(3000)
declare #Delimiter char(1) = ','
declare #result nvarchar(3000)
set #Version = 'Terça-feira, Quarta-feira, Sexta-feira, Segunda-feira';
with V as (select value v, Row_Number() over (order by (select 0)) n
from String_Split(#Version, #Delimiter)
)
SELECT #result = STUFF((SELECT ', ' + RTRIM(LTRIM(v))
FROM V
ORDER BY CASE RTRIM(LTRIM(v))
WHEN 'Segunda-feira' then 1
WHEN 'Terça-feira' then 2
WHEN 'Quarta-feira' then 3
WHEN 'Quinta-feira' then 4
WHEN 'Sexta-feira' then 5
END FOR XML PATH('')), 1, LEN(#Delimiter), '')
PRINT #result
This will be a much faster solution when your string has 1000 or more values to split. For table-valued functions, to have any ordering, you must apply "ORDER BY" at the place of use. This is because "SELECT" from a table without "ORDER BY" is by convention not having any sorting.
CREATE FUNCTION [dbo].[Split]
(
#String VARCHAR(max),
#Delimiter VARCHAR(max)
)
RETURNS #Data TABLE
(
[Order] INT IDENTITY(1,1),
[Value] VARCHAR(max)
)
AS
BEGIN
DECLARE #x XML = cast('<i>' + replace(#String, #Delimiter, '</i><i>') + '</i>' AS XML)
INSERT INTO #Data
SELECT v.value('.', 'varchar(max)') FROM #x.nodes('i') AS x(v)
RETURN
END
GO
If you can abide compatibility level 130 of SQL Server, you can use the String_Split() function.
With this and the Row_Number() function, you can return a table that includes the original sequence. For example:
declare #Version nvarchar(128)
set #Version = '1.2.3';
with V as (select value v, Row_Number() over (order by (select 0)) n
from String_Split(#Version, '.')
)
select
(select v from V where n = 1) Major,
(select v from V where n = 2) Minor,
(select v from V where n = 3) Revision
Note that Row_Number requires an ordering, but if you pass a literal value the results are in the parsed sequence. This isn't guaranteed to be the case with future SQL Server version, as according to the String_Split documentation, there is no official ordering. I doubt Microsoft will break this, at least before introducing a version of the function that returns the order as it should, but in the mean time you best not depend on this ordering when writing code that decides whether or not to launch the missile.
Returns:
Major Minor Revision
----- ----- --------
1 2 3

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

Select * from table where column = (any value from a comma delimited string)

The user selects various words from a drop down list and these values get added into a comma delimited string. When passing the string to a stored procedure I want it to select * from a table where that word exists.
Table
id----word
1-----cat
2-----dog
3-----mouse
4-----dog
string that is passed into the stored procedure is cat, dog so returning columns 1, 2 and 4.
Is there a way of doing this in sql server?
Use IN:
SELECT *
FROM your_table
WHERE word IN ('cat', 'dog')
you first need to make a function SplitCSV :
CREATE FUNCTION [dbo].[SplitCSV] (#CSVString VARCHAR(8000), #Delimiter CHAR(1))
RETURNS #temptable TABLE (items VARCHAR(8000))
AS
BEGIN
DECLARE #pos INT;
DECLARE #slice VARCHAR(8000);
SELECT #pos = 1;
IF LEN(#CSVString) < 1 OR #CSVString IS NULL RETURN;
WHILE #pos!= 0
BEGIN
SET #pos = CHARINDEX(#Delimiter,#CSVString);
IF #pos != 0
SET #slice = LEFT(#CSVString, #pos - 1);
ELSE
SET #slice = #CSVString;
IF( LEN(#slice) > 0)
INSERT INTO #temptable(Items) VALUES (#slice);
SET #CSVString = RIGHT(#CSVString, LEN(#CSVString) - #pos);
IF LEN(#CSVString) = 0 BREAK;
END
RETURN
END
GO
then you can use it like :
SELECT *
FROM myTable
WHERE ID IN (
SELECT items FROM [dbo].[SplitCSV]('1,2,3,4,5', ',')
)
SELECT *
FROM Table
WHERE '%,' + Word + ',%' LIKE ',' + #your_csv_param + ','
Extra commas at the begin and end of parameter and column are to prevent search to match cat with catfish for example.
If you want select all animal except mouse , you can use NOT IN
SELECT * FROM
TABLE
WHERE Word Not IN('Mouse')
So you can avoid type many type of animal
CREATE FUNCTION
ALTER FUNCTION [dbo].[fn_Split](#text varchar(8000), #delimiter varchar(20) = ' ')
RETURNS #Strings TABLE
(
position int IDENTITY PRIMARY KEY,
value varchar(8000)
)
AS
BEGIN
DECLARE #index int
SET #index = -1
WHILE (LEN(#text) > 0)
BEGIN
SET #index = CHARINDEX(#delimiter , #text)
IF (#index = 0) AND (LEN(#text) > 0)
BEGIN
INSERT INTO #Strings VALUES (#text)
BREAK
END
IF (#index > 1)
BEGIN
INSERT INTO #Strings VALUES (LEFT(#text, #index - 1))
SET #text = RIGHT(#text, (LEN(#text) - #index))
END
ELSE
SET #text = RIGHT(#text, (LEN(#text) - #index))
END
RETURN
END
----
select * from yourtable where column in ( select value from fn_Split(#para1,',')

Split string by comma in SQL Server 2008

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

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