Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing a varchar full of comma delimited values to a SQL Server IN function

Duplicate of
Dynamic SQL Comma Delimited Value Query
Parameterized Queries with Like and In

I have a SQL Server Stored Procedure where I would like to pass a varchar full of comma delimited values to an IN function. For example:

DECLARE @Ids varchar(50); SET @Ids = '1,2,3,5,4,6,7,98,234';  SELECT *  FROM sometable  WHERE tableid IN (@Ids); 

This does not work of course. I get the error:

Conversion failed when converting the varchar value '1,2,3,5,4,6,7,98,234' to data type int.

How can I accomplish this (or something relatively similar) without resorting to building dynamic SQL?

like image 837
Vance Smith Avatar asked May 18 '09 17:05

Vance Smith


People also ask

How get data from comma separated values in SQL?

In order to fetch the comma separated (delimited) values from the Stored Procedure, you need to make use of a variable with data type and size same as the Output parameter and pass it as Output parameter using OUTPUT keyword.

How split comma separated values in SQL stored procedure?

If you pass the comma separated (any separator) string to store procedure and use in query so must need to spit that string and then you will use it. Use dbo. ufnSplit function that I answered is better and clear code on store procedure.


2 Answers

Of course if you're lazy like me, you could just do this:

Declare @Ids varchar(50) Set @Ids = ',1,2,3,5,4,6,7,98,234,'  Select * from sometable  where Charindex(','+cast(tableid as varchar(8000))+',', @Ids) > 0 
like image 58
RBarryYoung Avatar answered Oct 08 '22 04:10

RBarryYoung


Don't use a function that loops to split a string!, my function below will split a string very fast, with no looping!

Before you use my function, you need to set up a "helper" table, you only need to do this one time per database:

CREATE TABLE Numbers (Number int  NOT NULL,     CONSTRAINT PK_Numbers PRIMARY KEY CLUSTERED (Number ASC)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY] ) ON [PRIMARY] DECLARE @x int SET @x=0 WHILE @x<8000 BEGIN     SET @x=@x+1     INSERT INTO Numbers VALUES (@x) END 

use this function to split your string, which does not loop and is very fast:

CREATE FUNCTION [dbo].[FN_ListToTable] (      @SplitOn              char(1)              --REQUIRED, the character to split the @List string on     ,@List                 varchar(8000)        --REQUIRED, the list to split apart ) RETURNS @ParsedList table (     ListValue varchar(500) ) AS BEGIN  /** Takes the given @List string and splits it apart based on the given @SplitOn character. A table is returned, one row per split item, with a column name "ListValue". This function workes for fixed or variable lenght items. Empty and null items will not be included in the results set.   Returns a table, one row per item in the list, with a column name "ListValue"  EXAMPLE: ---------- SELECT * FROM dbo.FN_ListToTable(',','1,12,123,1234,54321,6,A,*,|||,,,,B')      returns:         ListValue           -----------         1         12         123         1234         54321         6         A         *         |||         B          (10 row(s) affected)  **/    ---------------- --SINGLE QUERY-- --this will not return empty rows ---------------- INSERT INTO @ParsedList         (ListValue)     SELECT         ListValue         FROM (SELECT                   LTRIM(RTRIM(SUBSTRING(List2, number+1, CHARINDEX(@SplitOn, List2, number+1)-number - 1))) AS ListValue                   FROM (                            SELECT @SplitOn + @List + @SplitOn AS List2                        ) AS dt                       INNER JOIN Numbers n ON n.Number < LEN(dt.List2)                   WHERE SUBSTRING(List2, number, 1) = @SplitOn              ) dt2         WHERE ListValue IS NOT NULL AND ListValue!=''    RETURN  END --Function FN_ListToTable 

you can use this function as a table in a join:

SELECT     Col1, COl2, Col3...     FROM  YourTable         INNER JOIN FN_ListToTable(',',@YourString) s ON  YourTable.ID = s.ListValue 

Here is your example:

Select * from sometable where tableid in(SELECT ListValue FROM dbo.FN_ListToTable(',',@Ids) s) 
like image 45
KM. Avatar answered Oct 08 '22 05:10

KM.