Click here to Skip to main content
15,890,381 members
Articles / Programming Languages / SQL
Tip/Trick

Using comma separated value parameter strings in SQL IN clauses

Rate me:
Please Sign up or sign in to vote.
4.92/5 (23 votes)
7 May 2013CPOL2 min read 348.9K   273   24   23
Passing a comma separated list of values to an SQL query is all very well, but you can't just use them in an "IN" clause. This helps.

Introduction 

The SQL IN clause is very useful, since it allows you to specify exactly which values you want to return.

For this tip,  let's assume we have a database with this table:

SQL
CREATE TABLE [dbo].[CSVDemo](
	[Id] [int] NOT NULL,
	[Descr] [varchar](50) NOT NULL
) ON [PRIMARY]
GO

And this data:

Id	Descr
1	The first row
2	The second row
3	Another row
4	The final row

We can specify the rows we want to very easily:

SQL
SELECT Id, Desc FROM CSVDemo WHERE Id IN (1, 3)

And we get the data we expect:

Id	Descr
1	The first row
3	Another row

But what if we try to give it a parameter or other variable string list?

SQL
DECLARE @LIST VARCHAR(200)
SET @LIST = '1,3'
SELECT Id, Descr FROM CSVDemo WHERE Id IN (@LIST)

Answer:

Msg 245, Level 16, State 1, Line 3
Conversion failed when converting the varchar value '1,3' to data type int.

Which is SQL-speak for "you can't do that!"

So what can we do? 

We can't do it, because SQL has no concept of Lists, or array or other useful data structures - it only knows about tables (and table based information) so it converts the string list into a table structure when it compiles the command - and it can't compile a variable string, so it complains and you get annoyed. Or at least, I do.

What we have to do is convert the comma separated values into a table first. My initial version was inline, and rather messy, so I re-worked it to a user function and made it a bit more general purpose. 

USE [Testing] GO

SQL
/****** Object:  UserDefinedFunction [dbo].[CSVToTable]    Script Date: 04/28/2013 10:45:17 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE FUNCTION [dbo].[CSVToTable] (@InStr VARCHAR(MAX))
RETURNS @TempTab TABLE
   (id int not null)
AS
BEGIN
    ;-- Ensure input ends with comma
	SET @InStr = REPLACE(@InStr + ',', ',,', ',')
	DECLARE @SP INT
DECLARE @VALUE VARCHAR(1000)
WHILE PATINDEX('%,%', @INSTR ) <> 0 
BEGIN
   SELECT  @SP = PATINDEX('%,%',@INSTR)
   SELECT  @VALUE = LEFT(@INSTR , @SP - 1)
   SELECT  @INSTR = STUFF(@INSTR, 1, @SP, '')
   INSERT INTO @TempTab(id) VALUES (@VALUE)
END
	RETURN
END
GO

This creates a user function that takes a comma separated value string and converts it into a table that SQL does understand - just pass it the sting, and it works it all out. It's pretty obvious how it works, the only complexity is the REPLACE part which ensures the string is terminated with a single comma by appending one, and removing all double commas from the string. Without this, while loop becomes harder to process, as the final number might or might not have a terminating comma and that would have to be dealt with separately.

Using the code

Simple:

SQL
DECLARE @LIST VARCHAR(200)
SET @LIST = '1,3'
SELECT Id, Descr FROM CSVDemo WHERE Id IN (SELECT * FROM dbo.CSVToTable(@LIST))

History

  • 2013 Apr 28: First version.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
CEO
Wales Wales
Born at an early age, he grew older. At the same time, his hair grew longer, and was tied up behind his head.
Has problems spelling the word "the".
Invented the portable cat-flap.
Currently, has not died yet. Or has he?

Comments and Discussions

 
PraiseThanks for Sharing ! Saved my time. Pin
Member 1160005726-Jul-19 8:00
Member 1160005726-Jul-19 8:00 
PraiseAwesome! Pin
Just Russell24-May-18 3:50
professionalJust Russell24-May-18 3:50 
QuestionAnother option Pin
Pittsburger19-Dec-15 18:41
professionalPittsburger19-Dec-15 18:41 
QuestionUsage of Left function in your code Pin
ganesh.dks7-Jun-14 5:36
ganesh.dks7-Jun-14 5:36 
AnswerRe: Usage of Left function in your code Pin
OriginalGriff7-Jun-14 5:47
mveOriginalGriff7-Jun-14 5:47 
GeneralRe: Usage of Left function in your code Pin
ganesh.dks7-Jun-14 9:35
ganesh.dks7-Jun-14 9:35 
Okay thanks a lot for investing and explaining me I need to recall everything I learned to teach my student in 2009. Fortunately I landed into software but after a long time i.e. this year. I need to learn lot from experts like you.

I tried using your function in my proc but I still face the same problem you mentioned earlier (the conversion problem)

So I tried to directly use the code in my proc but again I get the same problem.

Here's my Procedure:-

I tried doing this but still didn't get it to work:-


SQL
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
alter procedure [dbo].[UserAdmin_UserRoles_IU]
@RoleID int,
@UserIDs varchar(max)
As
BEGIN
	Begin transaction
	--declare @Instr varchar(max)
	declare @TempTab table (id int)
	delete from UserRole where RoleID = @RoleID 
	--and UserID=(Select tbl.id from dbo.CSVToTable(@UserIDs) tbl)
	IF (@@ERROR <> 1)
	BEGIN 
	
		SET @UserIDs = REPLACE(@UserIDs + ',', ',,', ',')
		DECLARE @SP INT
		DECLARE @VALUE VARCHAR(1000)
		WHILE PATINDEX('%,%', @UserIDs ) <> 0 
		BEGIN
		   SELECT  @SP = PATINDEX('%,%',@UserIDs)
		   SELECT  @VALUE = LEFT(@UserIDs , @SP - 1)
		   SELECT  @UserIDs = STUFF(@UserIDs, 1, @SP, '')
		   INSERT INTO @TempTab(id) VALUES (@VALUE)
		   Insert into UserRole (UserID,RoleID )
		   Select tbl.id ,@RoleID RoleID
		   from
		   @TempTab tbl
		END
		IF (@@ERROR <> 1) 
			BEGIN
				commit transaction
			END
		ELSE
			BEGIN
				ROLLBACK TRAN
			END
	END 
END


Could you please tell me why.....pardon my ignorance please.
Ganesh
A new Programmer

Questionvery nice article. Have one question. Pin
bhumika_singh3-Jun-14 22:22
bhumika_singh3-Jun-14 22:22 
QuestionUseful, but a question remains... Pin
FrankEBailey14-Apr-14 8:26
FrankEBailey14-Apr-14 8:26 
AnswerRe: Useful, but a question remains... Pin
OriginalGriff15-Apr-14 0:48
mveOriginalGriff15-Apr-14 0:48 
GeneralThanks for the code Pin
Reneq26-Apr-14 18:25
Reneq26-Apr-14 18:25 
QuestionThank you. This article really helped. Pin
Uma MS24-Mar-14 0:38
Uma MS24-Mar-14 0:38 
Generalreally helps me.. Pin
anfil18-Jan-14 0:40
anfil18-Jan-14 0:40 
GeneralRe: really helps me.. Pin
OriginalGriff18-Jan-14 0:41
mveOriginalGriff18-Jan-14 0:41 
QuestionNice Tip Pin
Simon_Whale3-Dec-13 1:47
Simon_Whale3-Dec-13 1:47 
AnswerRe: Nice Tip Pin
OriginalGriff3-Dec-13 5:49
mveOriginalGriff3-Dec-13 5:49 
QuestionVery usee full Pin
ankit suthar23-Oct-13 20:33
ankit suthar23-Oct-13 20:33 
QuestionMy Vote of 5 Pin
Amol_B9-Jul-13 0:15
professionalAmol_B9-Jul-13 0:15 
AnswerRe: My Vote of 5 Pin
OriginalGriff9-Jul-13 0:24
mveOriginalGriff9-Jul-13 0:24 
GeneralRe: My Vote of 5 Pin
Amol_B9-Jul-13 0:37
professionalAmol_B9-Jul-13 0:37 
GeneralMy vote of 5 Pin
Nandakishore G N23-Jun-13 19:23
professionalNandakishore G N23-Jun-13 19:23 
Suggestionone change Pin
smonpara8-May-13 0:43
smonpara8-May-13 0:43 
GeneralRe: one change Pin
NewAmbition8-Oct-14 23:29
NewAmbition8-Oct-14 23:29 
GeneralMy vote of 5 Pin
croscwa28-Apr-13 2:49
croscwa28-Apr-13 2:49 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.