August 08, 2008

Using the IN Clause With Stored Procedures

Recently I have been working on creating a dynamic reporting engine for use within the DotNetNuke system, a method to allow for the execution of a stored procedure and the proper display of the results. This includes creating a list of parameters, including dynamically loaded lookup systems and more. Well the most complex item that I have had to condition for was how to deal with filter options that require the use of the SQL IN clause, there are many ways of doing this, but I have found a way that appears to work perfect for my needs, this will be explained in this posting.


This solution is provided as an example, and may not work 100% to meet your specific business needs, careful consideration must be taken when working with the code provided below as due to its dynamic nature SQL injection items need to be considered when investigating the input data provided to the stored procedure. If you have questions about the limitations or security surrounding this sample, please e-mail me or make a post to the forums on this site.


This example assumes that you already have a comma separated string that contains integer values that should be used as part of a list to be used inside of an "IN" clause. For example if you have a query that looks like the following.

FROM Reports
WHERE ReportId IN (@Reports)

This will NOT work in a stored procedure. The most common solution is to use dynamic SQL, which I personally do not like using. My solution will modify this to use a custom created Function that will parse the values into a table, then use that table to get the listing.


The Solution

As I mentioned above, the solution is very simple, create a function that converts the data into a table. Below is the needed procedure, please see the rest of the article for important notes.

CREATE FUNCTION dbo.funcListToTableInt(@list as varchar(8000), @delim as varchar(10))
RETURNS @listTable 
--Declare helper to identify the position of the delim
DECLARE @DelimPosition INT
--Prime the loop, with an initial check for the delim
SET @DelimPosition = CHARINDEX(@delim, @list)

--Loop through, until we no longer find the delimiter
WHILE @DelimPosition > 0
--Add the item to the table
INSERT INTO @listTable(Value)
VALUES(CAST(RTRIM(LEFT(@list, @DelimPosition - 1)) AS INT))
--Remove the entry from the List
SET @list = right(@list, len(@list) - @DelimPosition)

--Perform position comparison
SET @DelimPosition = CHARINDEX(@delim, @list)

--If we still have an entry, add it to the list
IF len(@list) > 0
insert into @listTable(Value)
values(CAST(RTRIM(@list) AS INT))


The above code creates a function that will process our input, converting each value to an integer and returning a single column table. The procedure created is called, funcListToTableInt. Now, with a simple modification to the sample query we are able to successfully run the query as part of a stored procedure.

FROM Reports
WHERE ReportId IN (
		    SELECT Value
		    FROM funcListToTableInt(@Reports,',')



This method provides a simple manner to convert a comma separated listing of values to something that can be used in an IN clause within SQL Server Stored procedures. Two parameters are passed to the function, allowing other delimiters to be used if needed. One could also use this for IN's of different datatypes, but a new function would be needed. I hope that this has helped someone solve a dynamic query situation. As always please provide any feedback below and any questions to the forum.

tags: Tutorials, SQL, .NET 1.1, .NET 2.0, .NET 3.5
comments powered by Disqus

Content provided in this blog is provided "AS-IS" and the information should be used at your own discretion.  The thoughts and opinions expressed are the personal thoughts of Mitchel Sellers and do not reflect the opinions of his employer.

Content Copyright

Content in this blog is copyright protected.  Re-publishing on other websites is allowed as long as proper credit and backlink to the article is provided.  Any other re-publishing or distribution of this content is prohibited without written permission from Mitchel Sellers.