December 4, 2003 at 7:09 am
Here is the problem,
I pass a parameter to my sp. That param is a varchar that contains a comma separated list of number that I want to have in my IN clause like this:
@list is : '1,2,3,4,5'
select * from test where var_id IN (@list)
var_id is an integer column ...
how can I get this to work ?
December 4, 2003 at 7:21 am
The only way to do this kind of thing is with dynamic SQL, e.g.
declare @sql varchar(255)
set @sql = 'select * from test where var_id in (' + @list + ')'
exec (@sql)
It seems good practice however, to always mention that dynamic SQL might not necessarily be the way to go - pitfalls as well as benefits and all that, which are discussed here:
http://www.algonet.se/~sommar/dynamic_sql.html
Cheers,
mia
Life moves pretty fast. If you don't stop and look around once in a while, you could miss it.
Cheers,
mia
Life moves pretty fast. If you don't stop and look around once in a while, you could miss it.
December 4, 2003 at 7:37 am
The thing is that I can't use exec (@sql) because I use the select statement in the FOR clause of a CURSOR declaration. I didn't find a way to put something else than a select in there.....
DECLARE MyCursor CURSOR FOR
SELECT ...
December 4, 2003 at 8:15 am
If necessary, you could select the results of the query into a temporary table and then use the cursor to iterate through the temporary table?
However, couldn't you do this without a cursor? As the values in @list are comma-separated, could you parse @list to get each value in turn and extract the records from the table individually, thus removing the need for the cursor. I would be inclined to do this if you're going to have to deal with the records individually anyway.
What I have in mind is something like the following:
declare @comma_pos int
declare @list varchar(255)
declare @value_as_int int
set @list = '1,2,3,4,5'
while len(@list) <> 0
begin
set @comma_pos = charindex(',', @list)
if @comma_pos <> 0
begin
-- Extract the value.
set @value_as_int = cast(substring(@list, 1, @comma_pos - 1) as int)
-- Remove the value from the string.
set @list = substring(@list, @comma_pos + 1, len(@list))
end
else
begin
-- The string must now only contain the final value.
set @value_as_int = cast (@list as int)
set @list = ''
end
-- Use the select to do whatever you need to do...
select * from test
where var_id = @value_as_int
end
Cheers,
mia
Life moves pretty fast. If you don't stop and look around once in a while, you could miss it.
Cheers,
mia
Life moves pretty fast. If you don't stop and look around once in a while, you could miss it.
December 4, 2003 at 8:30 am
Wow! Thanks. I'm always impressed when people take all that time to help others.
Have a wonderful day mia !
December 4, 2003 at 8:34 am
how about:
Declare @varlist varchar(255)
Set @varList = ',1,2,3,5,' -- Commas before and after
SELECT *
FROM Table_Name
WHERE CHARINDEX(',' + Convert(varchar, TableId) + ',', @varList) > 0
* Noel
December 4, 2003 at 8:41 am
And I'm always impressed at how often someone else has a much simpler solution ![]()
Learning new ways to think about things all the time on this site!
Cheers,
mia
Life moves pretty fast. If you don't stop and look around once in a while, you could miss it.
Cheers,
mia
Life moves pretty fast. If you don't stop and look around once in a while, you could miss it.
December 4, 2003 at 8:45 am
This site is simply the Best !!
2 times I posted and 2 times I got incredile solutions in less than an hour !!
Thanks to all of you.
December 4, 2003 at 9:06 am
Looks like Frank is away today but he normally refers people to these sites:
http://www.algonet.se/~sommar/arrays-in-sql.html
http://vyaskn.tripod.com/passing_arrays_to_stored_procedures.htm
Jeremy
December 4, 2003 at 9:09 am
From time to time even I have to work.
Frank
--
Frank Kalis
Microsoft SQL Server MVP
Webmaster: http://www.insidesql.org/blogs
My blog: http://www.insidesql.org/blogs/frankkalis/[/url]
December 4, 2003 at 1:07 pm
The query of noeld is ok on small tables but I ran it (with 2 numbers in the list) on a 75 million rows table and it took 8 minutes to run even with an empty resultset.
With the 2 numbers hardcoded it takes not even a second ! I will try mia statement !
December 4, 2003 at 1:50 pm
How about parsing the "List" into
something like ...
Declare @List Varchar(255)
set @list = '1,2,13,4,5'
Select Convert(Int, SubString(@List, StartPos, EndPos - StartPos + 1) ) as ListValues
From (
Select Min(Number) as StartPos,
NextComma -1 as EndPos
From (
Select Number,
Case When SubString(@List , Number, 1) <> ',' Then Number -1 Else 0 End as TheEnd,
CharIndex(',', @List + ',', Number) as NextComma
From Master.dbo.spt_Values
Where Type = 'P' and Number Between 1 and Len(@List)
) Parse
Group By NextComma
) ListValues
Then Either put results in #Temp table,
or just JOIN on the main query.
Once you understand the BITs, all the pieces come together ![]()
December 4, 2003 at 2:07 pm
I didn't know you were using 75 MILLIONS records. I should have warn you about the cast because is not using any index.
I have nothing with that many records but I would be interested if you can tell me how this performs :
DECLARE @List varchar( 255 )
SET @List = ',1,2,3,7,5,'
SELECT * From
TABLE
Where TABLEId IN(
SELECT CAST (SUBSTRING( @List , n.n + 1 , CHARINDEX( ',' , @List , n.n + 1 ) - n.n - 1 ) AS int) AS Value
FROM Numbers AS n
WHERE n.n BETWEEN 1 And LEN( @List ) - 1
And
SUBSTRING( @List , n.n , 1 ) = ','
)
Assuming you already Have a "small" table called Numbers with numbers from 1 to the Max number of parameters (maybe 1-100?)
* Noel
December 4, 2003 at 2:14 pm
And Also Try the difference with a join:
SELECT * From
TABLE JOIN (SELECT CAST (SUBSTRING( @List , n.n + 1 , CHARINDEX( ',' , @List , n.n + 1 ) - n.n - 1 ) AS int) AS Value FROM Numbers AS nWHERE n.n BETWEEN 1 And LEN( @List ) - 1 And SUBSTRING( @List , n.n , 1 ) = ',') VAlues(c) ON TABLE.TABLEID = VALUES.c
Please, post your results
* Noel
December 5, 2003 at 1:53 am
Hi,
when I'm passing data for use like this - for example when having key/value pairs with separators - e.g.,;
I use the following process;
CREATE FUNCTION Split_Varchar (@string varchar(8000),@sep varchar(1))
RETURNS
@ARRAY TABLE (ItemValue varchar(8000))
BEGIN
-- parse the attributetesting string and insert appropriate records
declare @value varchar(8000)
declare @start int
declare @finish int
declare @abort int
select @start = 1, @finish = 0, @abort=0
if ltrim(rtrim(@string)) = '' RETURN
if right(@string, 1) <> @sep select @string= @string+ @sep
WHILE @start<>0
BEGIN
select @abort = @abort+1
if @abort >8000 BREAK
select @finish = CHARINDEX(@sep, @string, @start)
if @finish= 0 BREAK
-- got the start and end points
SELECT @value = SUBSTRING(@string, @start, @finish - @start)
INSERT INTO @ARRAY (ITemValue) VALUES(convert(varchar(8000), @VALUE))
-- now move to the next value;
SELECT @start = @finish+1
IF @finish > len(@string) SELECT @start = 0
END
RETURN
END
this returns a table that you can reference, e.g.,
SELECT ItemValue
FROM dbo.Split_Varchar('123=54|124=54|776=76', '|')
that then returns a list of varchar ItemValues that you can then split down again - I've got 2 functions that do Get Key and Get Value returning these values as Integers.
you get the idea.
So taking the process forward (split_int returns ItemValue as an integer rather than a string);
SELECT T.*
from test T, dbo.Split_Int('1,2,3,4,5', ',') D
where
T.var_id = D.ItemValue
job done.
I often use this for bulk updating of data submitted from web-pages, e.g., a list of checkboxes on/off etc.
That way it can all be wrapped in a transaction as well.
hope this helps
cheers
Andy
Viewing 15 posts - 1 through 15 (of 17 total)
You must be logged in to reply to this topic. Login to reply