4

I have a CheckBoxList where users can select multiple items from the list. I then need to be able to pass these values to my Stored Procedure so they can be used in a WHERE condition like:

WHERE ID IN (1,2,3)

I tried doing this so that its a nvarchar parameter and i pass the string 1,2,3 with:

WHERE ID IN (@IDs)

But this returned the following error:

Conversion failed when converting the nvarchar value '1,2,3' to data type int

Any help would be much appreciated!

Curt
  • 94,964
  • 60
  • 257
  • 340
  • See http://stackoverflow.com/questions/878833/passing-a-varchar-full-of-comma-delimited-values-to-a-sql-server-in-function (or use a bitmask) – Alex K. Jan 07 '11 at 10:16

3 Answers3

11

There's a few ways of doing it. You could pass in the parameter as an XML blob like this example:

CREATE PROCEDURE [dbo].[uspGetCustomersXML]
    @CustomerIDs XML
AS
BEGIN
SELECT c.ID, c.Name
FROM [dbo].[Customer] c
JOIN @CustomerIDs.nodes('IDList/ID') AS x(Item) ON c.ID = Item.value('.', 'int' )
END
GO

--Example Use:
EXECUTE [dbo].[uspGetCustomersXML] '<IDList><ID>1</ID><ID>10</ID><ID>100</ID></IDList>'

Or pass in the values as CSV and use a split function to split the values out into a table variable (there's a lot of split functions out there, quick search will throw one up).

CREATE PROCEDURE [dbo].[uspGetCustomersCSV]
    @CustomerIDs VARCHAR(8000)
AS
BEGIN
SELECT c.Id, c.Name
FROM [dbo].[Customer] c
JOIN dbo.fnSplit(@CustomerIDs, ',') t ON c.Id = t.item
END
GO

--Example Use:
EXECUTE [dbo].[uspGetCustomersCSV] '1,10,100'

If you were using SQL 2008 or later, you could have used Table Valued Parameters which allow you to pass a TABLE variable in as a parameter. I blogged about these 3 approaches a while back, with a quick performance comparison.

AdaTheDev
  • 128,935
  • 26
  • 185
  • 187
  • Thanks for this. I used a WHERE IN (SELECT [values from XML]) clause to get results but never would've known this was possible previously. Cheers! – Curt Jan 10 '11 at 14:05
  • @Curt how to use the `[values from XML])` term in the `WHERE IN (SELECT [values from XML])` do you have a specific code? can you help me? sorry im new to this. – Albert Laure Nov 07 '13 at 02:00
1
alter procedure c2
(@i varchar(5))
as
begin
    declare @sq nvarchar(4000)
    set @sq= 'select * from test where id in (<has_i>) '
    SET @sq= REPLACE(@sq, '<has_i>', @i)
    EXECUTE sp_executesql  @sq
end

exec c2 '1,3'
Pops
  • 28,257
  • 34
  • 127
  • 149
-1

I did find a solution for a similar problem. It is used for a data driven subscription, but can be easily altered for use in a parameter. check my blog post here with a detailed description

If you are having problem converting it to a stored procedure call, just let me know.

Montfrooij
  • 85
  • 8
  • Can you expand a little your answer? Near link-only answers are not useful if the link ever goes broken. – orique Jul 17 '13 at 13:43
  • Sorry, I was rather late..... I will convert the blogpost into separate replies. For the whole story : the blogpost still works! – Montfrooij Apr 16 '18 at 14:13
  • It is a rather lengthy blog post and it is still online (and will be for some time) – Montfrooij Apr 16 '18 at 14:16
  • I have created a very simple table with the name tmpMultiSel with two columns (ID and Name) – Montfrooij Apr 16 '18 at 14:17
  • Here is what I did to make it ‘multi value’: 1. Create a function I did find a function that accepts two parameters and splits the delimited string (first parameter) into a temporary table. I found it http://www.codeproject.com/Articles/7938/SQL-User-Defined-Function-to-Parse-a-Delimited-Str but modified the name to my ‘habits’ _f_ParseText2Table If we test this function, it works like so: – Montfrooij Apr 16 '18 at 14:17
  • Meaning we can actually use this function to split a delimited string to a tempory table that we can join or select in a ‘IN’ clause (WHERE … IN (SELECT txt_value FROM dbo._f_ParseText2Table(‘1,2,3′,’,’)) 2. Create a report Next I created a report that has a dataset that links to the tmpMultiSel table (but could also link to a transactional table, that would make more sense) – Montfrooij Apr 16 '18 at 14:17
  • SELECT * FROM tmpMultiSel The second dataset is used to give the user the possibility to multi select some values from a table: – Montfrooij Apr 16 '18 at 14:17
  • The trick here is that this parameter (IDSel) may be left blank (as we cannot pass multiple values to a parameter via query or Data Driven Subscription) AND that we add an empty line in the second dataset (UNION ALL SELECT ”,”) to be able to select the ” value from the Data Driven Subscription. (make sure you type 2x single quotes comma 2x single quotes) 3. Create a parameter Here we have a parameter (ID) that we pass to the function: – Montfrooij Apr 16 '18 at 14:17
  • In ‘real life’ we would hide this parameter, but for testing purpose it is nicer to watch how it works. We add a second parameter (IDSel) that has multiple values and the available values selected from the second dataset. – Montfrooij Apr 16 '18 at 14:18
  • We set the default value for the first parameter (ID) to the split values of the second parameter (IDSel) As we test this report, it works like a charm, passing the two selected ID’s to the ID parameter, which in return passes its values to the first dataset. (what would be the transactional table) – Montfrooij Apr 16 '18 at 14:18
  • 4. Create the data driven subscription Now that we know this report works ‘interactive’ we can proceed to the data driven subscription. I’ve used a simple dataset that only has three columns (ID, IDSel and Mail). I did just select some static values, but you can easily modify it to work with a ‘real’ example where you select data from a table. Now we map this three columns to the appropriate fields and create a schedule for this subscription (once). – Montfrooij Apr 16 '18 at 14:19