Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2008 Forums
 Transact-SQL (2008)
 Variable in an IN

Author  Topic 

LopakaB
Starting Member

22 Posts

Posted - 2011-04-07 : 19:39:53
been searching for the answer but...
I have created a variable @var = 'a, b, c, d'
i am trying to use it in a select:
Select *
From Table
Where field IN @var

Keep getting errors... any help would be appreciated...
Thanks...

Lopaka

sunitabeck
Master Smack Fu Yak Hacker

5155 Posts

Posted - 2011-04-07 : 19:50:28
Intuitively, one would think this should work, but unfortunately it does not. Possible alternatives are:

1. Use dynamic sql (but beware of SQL injection risk)

2. Use something like this:
where ','+@var+',' like '%,'+field+',%'

3. Parse the comma-delimited @var into a temp table or table variable and join against that table.
Go to Top of Page

theboyholty
Posting Yak Master

226 Posts

Posted - 2011-04-08 : 05:43:13
Here's a handy bit of code I wrote when faced with an identical problem recently. I created a function from it but it depends on your circumstances - you could just run it as part of your code.


DECLARE @strText VARCHAR(1000)
SET @strText = 'one,two,three,four,five'

-- Makes sure there is a trailing comma, or else it won't work properly
SET @strText = @strText + CASE WHEN RIGHT(@strText,1) <> ',' THEN ',' ELSE '' END

CREATE TABLE #HoldingTable (Item VARCHAR(50))

WHILE LEN(@strText) > 0
BEGIN
INSERT INTO #HoldingTable
-- extracts characters up until the first comma and pops it into a temp table
SELECT LEFT(@strText,CHARINDEX(',',@strText)-1) as Item
--removes same text from @strText now it has been inserted into temp table
SET @strText = REPLACE(@strText,LEFT(@strText,CHARINDEX(',',@strText)),'')
END

SELECT Item FROM #HoldingTable


Then you can just go SELECT * FROM TABLE WHERE FIELD IN (SELECT Item FROM #HoldingTable) or even better, do an inner join onto the #HoldingTable.



---------------------------------------------------------------------------------
http://www.mannyroadend.co.uk The official unofficial website of Bury Football Club
Go to Top of Page

theboyholty
Posting Yak Master

226 Posts

Posted - 2011-04-08 : 05:45:57
Oh and just for fun and because its Friday and sunny, here's the code you could use to reverse the process:


DECLARE @strOutput VARCHAR(1000)
SET @strOutput = ''

SELECT @strOutput = @strOutput + Item + ', '
FROM (SELECT Item FROM #HoldingTable) x

-- Uses case statement to handle an empty table
SELECT CASE WHEN LEN(@strOutput) > 0 THEN LEFT(@strOutput,LEN(@strOutput)-1) ELSE @strOutput END as CSVString

DROP TABLE #HoldingTable



---------------------------------------------------------------------------------
http://www.mannyroadend.co.uk The official unofficial website of Bury Football Club
Go to Top of Page

webfred
Master Smack Fu Yak Hacker

8781 Posts

Posted - 2011-04-08 : 07:46:25
You can build your own function and use it like Sunita already told.
Here is an example from somewhere on sqlteam.com:
CREATE FUNCTION dbo.fnParseList
(
@Delimiter CHAR,
@Text varchar(max)
)
RETURNS @Result TABLE (RowID SMALLINT IDENTITY(1, 1) PRIMARY KEY, Data VARCHAR(8000))
AS

BEGIN
DECLARE @NextPos INT,
@LastPos INT

SELECT @NextPos = CHARINDEX(@Delimiter, @Text, 1),
@LastPos = 0

WHILE @NextPos > 0
BEGIN
INSERT @Result
(
Data
)
SELECT SUBSTRING(@Text, @LastPos + 1, @NextPos - @LastPos - 1)

SELECT @LastPos = @NextPos,
@NextPos = CHARINDEX(@Delimiter, @Text, @NextPos + 1)
END

IF @NextPos <= @LastPos
INSERT @Result
(
Data
)
SELECT SUBSTRING(@Text, @LastPos + 1, DATALENGTH(@Text) - @LastPos)

RETURN
END
select * from dbo.fnParseList(',','0976-009,3455-076,1234-123,2345-678,9999-878,2222-555')



No, you're never too old to Yak'n'Roll if you're too young to die.
Go to Top of Page

sunitabeck
Master Smack Fu Yak Hacker

5155 Posts

Posted - 2011-04-08 : 08:11:13
Let us say you are worried about your job and want to do something that works, but is completely incomprehensible to anyone else. Then, you could do something like this to parse the comma-separated string into a table:
declare @var varchar(max);
set @var = '0976-009,3455-076,1234-123,2345-678,9999-878,2222-555';

declare @xml xml;
select @xml =
cast('<r>'+replace(
(select @var for xml path ('')) ,',','</r><r>')+'</r>'
as xml)

select c1.value('(./text())[1]','NVARCHAR(50)') from
@xml.nodes('/r') T(c1);
Mind you, I am not advocating using it, it is only for academic interest . There are better and faster methods, including the one that webfred posted, but a little bit of obscurity never hurt anyone.
Go to Top of Page

Lamprey
Master Smack Fu Yak Hacker

4614 Posts

Posted - 2011-04-08 : 11:48:52
Everything you ever wanted to know about using Arrays in SQL:
http://www.sommarskog.se/arrays-in-sql.html
Go to Top of Page

mmarovic
Aged Yak Warrior

518 Posts

Posted - 2011-04-08 : 15:52:44
quote:
Originally posted by Lamprey

Everything you ever wanted to know about using Arrays in SQL:
http://www.sommarskog.se/arrays-in-sql.html



Well I have found a pretty good solution for a specific problem that was not mentioned in that article: [url]http://www.sql-server-performance.com/articles/dba/list_random_values_p1.aspx[/url]

Mirko

My blog: http://mirko-marovic-eng.blogspot.com/
Go to Top of Page

jcelko
Esteemed SQL Purist

547 Posts

Posted - 2011-04-11 : 19:24:17
quote:
Originally posted by LopakaB

been searching for the answer but...
I have created a variable @var = 'a, b, c, d'
i am trying to use it in a select:
Select *
From Table
Where field IN @var

Keep getting errors... any help would be appreciated...
Thanks...

Lopaka




Please read a book --ANY BOOK -- on SQL. You even called a skeleton "column" by the name "field" to tell us you have no idea how SQL and RDBMS works.

Do this with a long parameter list. You can pass up to 2000+ parameters in T-SQL, which is more than you probably will ever need. The compiler will do all that error checking that the query version and the procedural code simply do not have unless you write a full parser with the standard error codes. You can now pass local variables to your procedure; you can pass other data types and get automatic conversions, etc. In short, this is just good software engineering.

CREATE PROCEDURE LongList
(@p1 INTEGER = NULL,
@p2 INTEGER = NULL,
@p3 INTEGER = NULL,
@p4 INTEGER = NULL,
@p5 INTEGER = NULL)

x IN (SELECT parm
FROM (VALUES (@p1), (@p2), (@p3), (@p4), (@p5)) AS X(parm)
WHERE parm IS NOT NULL;

You get all the advantages of the real compiler and can do all kinds of things with the values.




--CELKO--
Books in Celko Series for Morgan-Kaufmann Publishing
Analytics and OLAP in SQL
Data and Databases: Concepts in Practice
Data, Measurements and Standards in SQL
SQL for Smarties
SQL Programming Style
SQL Puzzles and Answers
Thinking in Sets
Trees and Hierarchies in SQL
Go to Top of Page
   

- Advertisement -