How to select each row into a variable in SQL Server - sql

We have a function that turns a delimited list into a table:
select * from dbo.fn_rpt_ParseValues('abc|123|test','|')
Results:
abc
123
test
How can I get each row into a SQL variable? For example:
#Name = 'abc'
#Phone = '123'
#Comment = 'test'
Thanks!

declare #S varchar(100) = 'abc|123|test'
declare #Name varchar(10)
declare #Phone varchar(10)
declare #Comment varchar(10)
select #Name = X.value('x[1]', 'varchar(10)'),
#Phone = X.value('x[2]', 'varchar(10)'),
#Comment = X.value('x[3]', 'varchar(10)')
from (select cast('<x>'+replace(#S, '|', '</x><x>')+'</x>' as xml)) as T(X)
select #Name, #Phone, #Comment

DECLARE #Split table(
RowIndex int IDENTITY(1,1)
,Item varchar(200));
INSERT INTO #Split
SELECT * from dbo.fn_rpt_ParseValues('abc|123|test','|');
DECLARE #Name varchar(50);
DECLARE #Phone varchar(50);
DECLARE #Comment varchar(100);
SET #Name = (SELECT Item FROM #Split WHERE RowIndex=1);
SET #Phone = (SELECT Item FROM #Split WHERE RowIndex=2);
SET #Comment = (SELECT Item FROM #Split WHERE RowIndex=3);

Assuming that the rows are ordered, you want to do a pivot to turn them into columns.
Another option is to have your parse function (or a modified version) return a single row result set (table-valued function) and use CROSS/OUTER APPLY to append them to a row:
http://msdn.microsoft.com/en-us/library/ms174853.aspx

Related

Insert into Table Variable values from a comma separated list

declare #List varchar(25) = '2,3,4'
declare #Delinquencies table (id int);
insert into #Delinquencies(id) values('2'),('3'),('4'); --Line in question
#List is being populated with a string populated from an SSRS report for which choices they have picked. Now the way my stored procedure is running, I need to be able insert into my table variable based on what varchar list is coming through. How can I insert into a table variable with a dynamic varchar list? What is listed here is about as close to the testing format as I can come.
I am using SQL Server 2008.
Example
#List = '1'
insert into #Delinquencies(id) values('1')
And any combination up to
#List = '1,2,3,4'
insert into #Delinquencies(id) values('1'),('2'),('3'),('4')
Using one of the split string functions from here..
declare #List varchar(25) = '2,3,4';
declare #Delinquencies table (id int);
;with cte
as
(select * from
[dbo].[SplitStrings_Numbers](#list,',')
)
insert into #Delinquencies(id)
select * from cte
u need to create a dbo.StringSplit function
which takes two parameter (string, delimiter)
CREATE function [dbo].[StringSplit](
#String varchar (max),
#Delimiter nvarchar (10)
)
returns #ValueTable table ([Value] varchar(max))
begin
declare #NextString varchar(max)
declare #Pos int
declare #NextPos int
declare #CommaCheck nvarchar(1)
--Initialize
set #NextString = ''
set #CommaCheck = right(#String,1)
--Check for trailing Comma, if not exists, INSERT
--if (#CommaCheck <> #Delimiter )
set #String = #String + #Delimiter
--Get position of first Comma
set #Pos = charindex(#Delimiter,#String)
set #NextPos = 1
--Loop while there is still a comma in the String of levels
while (#pos <> 0)
begin
set #NextString = substring(#String,1,#Pos - 1)
insert into #ValueTable ( [Value]) Values (#NextString)
set #String = substring(#String,#pos +1,len(#String))
set #NextPos = #Pos
set #pos = charindex(#Delimiter,#String)
end
return
end
and then you can use it like below
declare #List varchar(25) = '2,3,4'
SELECT value from dbo.StringSplit(#List,',')
Here is a parser which returns the sequence as well.
For example:
Select * from [dbo].[udf-Str-Parse]('126,256,512',',')
Returns
Key_PS Key_Value
1 126
2 256
3 512
The UDF
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',' ')
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

Read string with comma and insert into sql table single row

Table
Column A Column B Column C
----------------------------------------------
I have an input string like (Apple,Banana,Orange). I need to insert these values to the above table.
Result should be like
ColumnA Column B Column C
-------------------------------------------
Apple Banana Orange
Is it possible using a procedure that takes the input parameter as a csv string?
Please use the below code to get the list of column name. You can pass the same to SP for inserting to your table.
BEGIN
DECLARE #str VARCHAR(2000)
DECLARE #input VARCHAR(4000)
DECLARE #ind Int
DECLARE #Count int
DECLARE #max int
SET #max =0
DECLARE #table TABLE(ColumnA varchar(10),ColumnB varchar(10),ColumnC varchar(10))
DECLARE #Result TABLE (ID int identity(1,1),value varchar(1000))
SET #input ='Apple,Banana,Orange'
IF(#input is not null)
BEGIN
SET #ind = CharIndex(',',#input)
WHILE #ind > 0
BEGIN
SET #str = SUBSTRING(#input,1,#ind-1)
SET #input = SUBSTRING(#input,#ind+1,LEN(#input)-#ind)
INSERT INTO #Result values (#str)
SET #ind = CharIndex(',',#input)
END
SET #str = #input
INSERT INTO #Result values (#str)
END
SET #Count = (SELECT Max(ID) from #Result)
WHILE #Count > #max
BEGIN
SET #max = #max +1
DECLARE #Value varchar(1000)
SET #Value = (SELECT value from #Result WHERE ID =#max)
SELECT #value
END
END
Please check following SQL script which splits input string parameter and inserts into a table
Please note that I use SQL split string function dbo.Split and you can find the source codes at referred SQL tutorial
You will need such a user defined split function unless you use SQL Server 2016
/*
create table TableT (
[Column A] varchar(100),
[Column B] varchar(100),
[Column C] varchar(100)
)
*/
declare #string varchar(max) = 'Apple,Banana,Orange'
select * from dbo.Split(#string, ',')
insert into TableT
select
MAX([Column A]) as [Column A],
MAX([Column B]) as [Column B],
MAX([Column C]) as [Column C]
from (
select
case when id = 1 then val end as [Column A],
case when id = 2 then val end as [Column B],
case when id = 3 then val end as [Column C]
from dbo.Split(#string, ',')
) s
select * from TableT
Please make use of the below query. Its working fine in SQL Server 2012.
BEGIN
DECLARE #input VARCHAR(4000)
DECLARE #str VARCHAR(4000)
DECLARE #Query NVARCHAR(max)
SET #input ='(Apple,Banana,Orange)'
IF(#input is not null)
BEGIN
SET #str = (SELECT REPLACE(#input,'(','('''))
SET #str = (SELECT REPLACE(#str,')',''')'))
SET #str = (SELECT REPLACE(#str,',',''','''))
SET #Query ='INSERT INTO MyTable (ColumnA,ColumnB,ColumnC)VALUES '+#str
Exec (#Query)
END
END

Split two comma-separated values by comma delimeter and store in two columns of same temporary table

Again I need your help in writing a SQL query.
I have two comma-separated strings:
1,2,3 and a,b,c
Number of elements (e.g. 1, 2 & 3) in both the comma-separated values are the same. In the given example, its 3.
What I want is to split the comma-separated values by comma delimeter and store them in two columns of same temporary table.
I am using SQL Server 2012.
I would suggest you to create an UDF which accepts the delimited string input and returns a table with ID, something like below (so this can be reused where required):
Go
CREATE FUNCTION [dbo].[ReturnTableFromDelimetedStringWithID] (#list VARCHAR(MAX), #delimiter VARCHAR(30), #inclblanks BIT)
RETURNS #table TABLE (id INT NOT NULL PRIMARY KEY, item VARCHAR(3000) )
AS
BEGIN
DECLARE #item VARCHAR(3000)
DECLARE #delim VARCHAR(30)
DECLARE #str VARCHAR(MAX)
DECLARE #pos INT
DECLARE #id INT
SET #id = 0
SET #delim = #delimiter
IF #delim='' SET #delim=','
SET #str = #list + #delim
WHILE CHARINDEX (#delim, #str) > 0
BEGIN
SET #id = #id + 1
SET #pos = CHARINDEX (#delim, #str)
SET #item = CONVERT(VARCHAR(3000), SUBSTRING( #str, 1, #pos - 1))
SET #str = SUBSTRING( #str, #pos + LEN(#delim), LEN( #str))
IF #inclblanks=1
INSERT INTO #table VALUES (#id, #item)
ELSE
IF #item<>'' INSERT INTO #table VALUES (#id, #item)
END
RETURN
END
GO
Then, you can query like below:
DECLARE #str1 VARCHAR(MAX) = '1,2,3'
DECLARE #str2 VARCHAR(MAX)= 'a,b,c'
DECLARE #delimiter CHAR(1) = ','
DECLARE #TmpTbl3 TABLE (Col1 VARCHAR(50), Col2 VARCHAR(50))
INSERT INTO #TmpTbl3
SELECT t1.c2, t2.c2
FROM
(
SELECT id [c1], item [c2] FROM dbo.ReturnTableFromDelimetedStringWithID(#str1, ',', 0)
) as t1
INNER JOIN
(
SELECT id [c1], item [c2] FROM dbo.ReturnTableFromDelimetedStringWithID(#str2, ',', 0)
) AS t2 ON t1.c1=t2.c1
--SELECT * FROM #TmpTbl3
This would probably be the best way.
I have figured out the solution. But I would like to post it so that it could be helpful to other people or you can guide me to make it more effective -
DECLARE #xml1 xml
DECLARE #xml2 xml
DECLARE #str1 VARCHAR(MAX)
DECLARE #str2 VARCHAR(MAX)
DECLARE #delimiter CHAR(1)
DECLARE #TmpTbl1 TABLE (Id INT IDENTITY(1,1), Col1 VARCHAR(50))
DECLARE #TmpTbl2 TABLE (Id INT IDENTITY(1,1), Col2 VARCHAR(50))
DECLARE #TmpTbl3 TABLE (Col1 VARCHAR(50), Col2 VARCHAR(50))
SET #str1 = '1,2,3'
SET #str2 = 'a,b,c'
SET #delimiter = ','
SET #xml1 = CAST(('<X>'+replace(#str1, #delimiter, '</X><X>')+'</X>') AS XML)
SET #xml2 = CAST(('<X>'+replace(#str2, #delimiter, '</X><X>')+'</X>') AS XML)
INSERT INTO #TmpTbl1 (Col1)
SELECT C.value('.', 'VARCHAR(50)') AS value FROM #xml1.nodes('X') AS X(C)
INSERT INTO #TmpTbl2 (Col2)
SELECT C.value('.', 'VARCHAR(50)') AS value FROM #xml2.nodes('X') AS X(C)
INSERT INTO #TmpTbl3 (Col1, Col2)
SELECT tmp1.Col1, tmp2.Col2
FROM #TmpTbl1 tmp1
INNER JOIN #TmpTbl2 tmp2 ON tmp1.Id = tmp2.Id
SELECT Col1, Col2 FROM #TmpTbl3

convert string into int SQL Server

This is the scenario:
My app will have the following:
A listbox (The checkbox property enabled) that will display a list of Something.
The user will select from the listbox (multiselect) by using the checkbox.
I will loop into All the checked items and store the ID's into an array. I will store the ID's into something like this separating the ID with a comma (1,2,3,4) and then I will use length -1 to delete the last comma.
How can I convert the string 1,2,3,4 into an integer type of data if my stored procedure is like this?
Select * from tblSomething Where ID in (1,2,3,4)
You can use the following SQL function.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION [dbo].[CommaSeparatedToString]
(
#psCSString VARCHAR(8000)
)
RETURNS #otTemp TABLE(sID VARCHAR(20))
AS
BEGIN
DECLARE #sTemp VARCHAR(50)
WHILE LEN(#psCSString) > 0
BEGIN
SET #sTemp = LEFT(#psCSString, ISNULL(NULLIF(CHARINDEX(',', #psCSString) - 1, -1),
LEN(#psCSString)))
SET #psCSString = SUBSTRING(#psCSString,ISNULL(NULLIF(CHARINDEX(',', #psCSString), 0),
LEN(#psCSString)) + 1, LEN(#psCSString))
INSERT INTO #otTemp VALUES (#sTemp)
END
RETURN
END
And call in your stored procedure like
Select * from tblSomething
Where ID in (SELECT * FROM CommaSeparatedToString('1,2,3,4'))
You can use the
SELECT CAST(MyVarcharCol AS INT) FROM Table
SELECT CONVERT(INT, MyVarcharCol) FROM Table
refer this link
http://msdn.microsoft.com/en-us/library/ms187928.aspx
You need to create dynamic query for this
e.g you are getting list of values in #values paramter so prepare and run the dynamic query like this
DECLARE #query NVARCHAR(500)
DECLARE #values VARCHAR(200)
SET #values='1,2'
SET #query =N'Select * from tblSomething Where ID in ( ' + #values + ')'
SELECT #query
EXEC #Query
Use this function to split the value:
CREATE FUNCTION [dbo].[udfSplitCSV]
(
#String varchar (max),
#Delimiter varchar (10) = ','
)
RETURNS #ValueTable TABLE ([Row] int IDENTITY(1,1), [Value] varchar(max), [Length] int, [Duplicate] int NULL)
BEGIN
DECLARE #NextString varchar(max)
DECLARE #Pos int
DECLARE #NextPos int
IF #String IS NULL RETURN
--Initialize
SET #NextString = ''
SET #String = #String + #Delimiter
--Get position of first Comma
SET #Pos = charindex(#Delimiter,#String)
SET #NextPos = 1
--Loop while there is still a comma in the String
WHILE (#Pos <> 0)
BEGIN
SET #NextString = RTrim(LTrim(SubString(#String,1,#Pos - 1)))
INSERT INTO #ValueTable ([Value], [Length]) VALUES (#NextString, Len(#NextString))
SET #String = SubString(#String,#Pos+1,Len(#String))
SET #NextPos = #Pos
SET #Pos = CharIndex(#Delimiter,#String)
END
UPDATE #ValueTable
SET [Duplicate] = X.Duplicate
FROM #ValueTable VT
INNER JOIN (Select [Row], [Value], Row_Number() OVER (Partition By [Value] ORDER BY [Value], [Row]) as Duplicate FROM #ValueTable) X
ON X.[Row] = VT.[Row]
RETURN
END
-- Select * from dbo.udfSplitCSV('a , c b,c, a', ',')
When you are storing a bunch of IDs into the array, store with single quote.
so it will be ('1','2','3').
Then you no need to covert IDs into integer.

How to convert comma separated NVARCHAR to table records in SQL Server 2005?

I have a list of ids separated by comma like:
1,17,25,44,46,67,88
I want to convert them to a table records ( into a temporary table ) like
#tempTable
number_
--------
1
17
25
44
46
67
88
It is possible with a function, a table-valued one ?
Why I want this ? I want to use for INNER JOIN clause (into stored procedure) with another table(s) like as:
SELECT a,b,c FROM T1
INNER JOIN functionNameWhichReturnsTable
ON functionNameWhichReturnsTable.number_ = T1.a
I cannot use IN because I will use stored procedure which accepts a parameter of type NVARCHAR. That parameter will provide the list of ids.
Thank you
Possible duplicate of separate comma separated values and store in table in sql server.
Please try a precise one from Comma-Delimited Value to Table:
CREATE FUNCTION [dbo].[ufn_CSVToTable] ( #StringInput VARCHAR(8000), #Delimiter nvarchar(1))
RETURNS #OutputTable TABLE ( [String] VARCHAR(10) )
AS
BEGIN
DECLARE #String VARCHAR(10)
WHILE LEN(#StringInput) > 0
BEGIN
SET #String = LEFT(#StringInput,
ISNULL(NULLIF(CHARINDEX(#Delimiter, #StringInput) - 1, -1),
LEN(#StringInput)))
SET #StringInput = SUBSTRING(#StringInput,
ISNULL(NULLIF(CHARINDEX(#Delimiter, #StringInput), 0),
LEN(#StringInput)) + 1, LEN(#StringInput))
INSERT INTO #OutputTable ( [String] )
VALUES ( #String )
END
RETURN
END
GO
Check the requirement in other way using XML:
DECLARE #param NVARCHAR(MAX)
SET #param = '1:0,2:1,3:1,4:0'
SELECT
Split.a.value('.', 'VARCHAR(100)') AS CVS
FROM
(
SELECT CAST ('<M>' + REPLACE(#param, ',', '</M><M>') + '</M>' AS XML) AS CVS
) AS A CROSS APPLY CVS.nodes ('/M') AS Split(a)
Here's a trick that doesn't need a function or XML.
Basically the string gets transformed into a single insert statement for a temporary table.
The temp table can then be used for further processing.
IF OBJECT_ID('tempdb..#tmpNum') IS NOT NULL
DROP TABLE #tmpNum;
CREATE TABLE #tmpNum (num int);
DECLARE #TEXT varchar(max) = '1,17,25,44,46,67,88';
DECLARE #InsertStatement varchar(max);
SET #InsertStatement = 'insert into #tmpNum (num) values ('+REPLACE(#TEXT,',','),(')+');';
EXEC (#InsertStatement);
-- use the temp table
SELECT *
FROM YourTable t
WHERE t.id IN (SELECT DISTINCT num FROM #tmpNum);
This method is usable for up to 1000 values.
Because 1000 is the max limit of a row value expression.
Also, as Stuart Ainsworth pointed out.
Since this method uses Dynamic Sql, be wary of code injection and don't use it for strings based on user input.
Side-note
Starting from MS Sql Server 2016, one could simply use the STRING_SPLIT function.
DECLARE #TEXT varchar(max);
SET #TEXT = '1,17,25,44,46,67,88';
SELECT t.*
FROM YourTable t
JOIN (SELECT DISTINCT CAST(value AS INT) num FROM STRING_SPLIT(#TEXT, ',')) nums
ON t.id = nums.num;
Completing the answers, you could also use the CSV string to store multiple values in multiple columns:
--input sql text
declare #text_IN varchar(max) ='text1, text1.2, text1.3, 1, 2010-01-01\r\n text2, text2.2, text2.3, 2, 2016-01-01'
Split the csv file into rows:
declare #temptable table (csvRow varchar(max))
declare #DelimiterInit varchar(4) = '\r\n'
declare #Delimiter varchar(1) = '|'
declare #idx int
declare #slice varchar(max)
set #text_IN = REPLACE(#text_IN,#DelimiterInit,#Delimiter)
select #idx = 1
if len(#text_IN)<1 or #text_IN is null return
while #idx!= 0
begin
set #idx = charindex(#Delimiter,#text_IN)
if #idx!=0
set #slice = left(#text_IN,#idx - 1)
else
set #slice = #text_IN
if(len(#slice)>0)
insert into #temptable(csvRow) values(#slice)
set #text_IN = right(#text_IN,len(#text_IN) - #idx)
if len(#text_IN) = 0 break
end
Split rows into columns:
;WITH XMLTable (xmlTag)
AS
(
SELECT CONVERT(XML,'<CSV><champ>' + REPLACE(csvRow,',', '</champ><champ>') + '</champ></CSV>') AS xmlTag
FROM #temptable
)
SELECT RTRIM(LTRIM(xmlTag.value('/CSV[1]/champ[1]','varchar(max)'))) AS Column1,
RTRIM(LTRIM(xmlTag.value('/CSV[1]/champ[2]','varchar(max)'))) AS Column2,
RTRIM(LTRIM(xmlTag.value('/CSV[1]/champ[3]','varchar(max)'))) AS Column3,
RTRIM(LTRIM(xmlTag.value('/CSV[1]/champ[4]','int'))) AS Column4,
RTRIM(LTRIM(xmlTag.value('/CSV[1]/champ[5]','datetime'))) AS Column5
FROM XMLTable
The following works:
declare #parStoreNo As varchar(8000) = '1,2,3,4'
CREATE TABLE #parStoreNo (StoreNo INT)-- drop #parStoreNo
declare #temptable VARCHAR(1000) = #parStoreNo
declare #SQL VARCHAR(1000)
SELECT #SQL = CONVERT(VARCHAR(1000),' select ' + REPLACE(ISNULL(#temptable,' NULL '),',', ' AS Col UNION ALL SELECT '))
INSERT #parStoreNo (StoreNo)
EXEC (#SQL)
I am using XML Function as below...
DECLARE #str VARCHAR(4000) = '6,7,7,8,10,12,13,14,16,44,46,47,394,396,417,488,714,717,718,719,722,725,811,818,832,833,836,837,846,913,914,919,922,923,924,925,926,927,927,928,929,929,930,931,932,934,935,1029,1072,1187,1188,1192,1196,1197,1199,1199,1199,1199,1200,1201,1202,1203,1204,1205,1206,1207,1208,1209,1366,1367,1387,1388,1666,1759,1870,2042,2045,2163,2261,2374,2445,2550,2676,2879,2880,2881,2892,2893,2894'
Declare #x XML
select #x = cast('<A>'+ replace(#str,',','</A><A>')+ '</A>' as xml)
select t.value('.', 'int') as inVal
from #x.nodes('/A') as x(t)
I prefer this because not need to create any separate function and proc. Also I don't have to opt dynamic SQL query which I prefer most.
Convert Comma Separated String to Table
DECLARE #str VARCHAR(4000) = '6,7,7,8,10,12,13,14,16,44,46,47,394,396,417,488,714,717,718,719,722,725,811,818,832'
DECLARE #x XML
select #x = cast('<A>'+ replace(#str,',','</A><A>')+ '</A>' as xml)
select t.value('.', 'int') as inVal
from #x.nodes('/A') as x(t)
Try this code
SELECT RTRIM(part) as part
INTO Table_Name
FROM dbo.splitstring(#Your_Comma_string,',')
splitstring Function is as follows
CREATE FUNCTION dbo.splitstring ( #stringToSplit VARCHAR(MAX) )
RETURNS
#returnList TABLE ([Name] [nvarchar] (500))
AS
BEGIN
DECLARE #name NVARCHAR(255)
DECLARE #pos INT
WHILE CHARINDEX(',', #stringToSplit) > 0
BEGIN
SELECT #pos = CHARINDEX(',', #stringToSplit)
SELECT #name = SUBSTRING(#stringToSplit, 1, #pos-1)
INSERT INTO #returnList
SELECT #name
SELECT #stringToSplit = SUBSTRING(#stringToSplit, #pos+1, LEN(#stringToSplit)-#pos)
END
INSERT INTO #returnList
SELECT #stringToSplit
RETURN
END