Reputation: 191
I'm looking to pass a theoretically unlimited number of IDs to a stored procedure as one variable and have it return all matching records. When using a list and IN statement I'm getting an error as ProviderID
datatype is INT and it's treating my list as strings.
DECLARE @ProviderList varchar(max)
SET @ProviderList = '1001,1002'
SELECT *
FROM tblProviders
WHERE ProviderID IN ( @ProviderList )
--Error: Error converting data type varchar to bigint. when used
Separating the IDs like below works...but as there's no way to know how many IDs will be searched at once it would be messy to have potential placeholder variables which aren't required.
DECLARE @ProviderOne varchar(max)
SET @ProviderOne = '1001'
DECLARE @ProviderTwo varchar(max)
SET @ProviderTwo = '1002'
SELECT *
FROM tblProviders
WHERE ProviderID IN ( @ProviderOne, @ProviderTwo )
Upvotes: 0
Views: 9792
Reputation: 1
DECLARE @ProviderList varchar(max)
Declare @sqlstring nvarchar(2000)
SET @ProviderList = '100,200,300'
set @sqlstring = 'SELECT * FROM temptable where Num_Key in (' + @ProviderList + ')'
--select @sqlstring
execute sp_executesql @sqlstring
Upvotes: 0
Reputation: 1569
If you're using SQL Server 2016 or above, or Azure SQL you can just use JSON:
DECLARE @ProviderList varchar(max)
SET @ProviderList = '[1001,1002]'
SELECT *
FROM tblProviders
WHERE ProviderID IN ( SELECT CAST(p.[Value] AS INT) FROM OPENJSON(@ProviderList) p )
It is the fastest and most secure method available
Upvotes: 0
Reputation: 95588
A couple ways to do this. One is to do a delimited string and then splitting it out. As I'm not sure what version of SQL Server you're on, you can find a copy of Jeff Moden's Delimited String splitter here.
Then you can do something like:
SELECT *
FROM MyTable MT
WHERE MT.MyValues IN (SELECT Item FROM dbo.delimitedSplit8k(@DelimString,',');
The alternative is to use a custom table-value type. This is where you can create a datatype that is in the form of a table. So, for example:
CREATE TYPE IDs AS TABLE (ID int);
GO
DECLARE @ID IDs;
INSERT INTO @ID
VALUES (1),(2),(3)
SELECT *
FROM MyTable MT
WHERE MT.MyValues IN (SELECT ID FROM @ID);
GO
--Clean up
--DROP TYPE IDs;
Any questions, please comment.
Upvotes: 2
Reputation: 28652
You can accept input as csv and then you can convert csv to list and pass as in parameter
SELECT *
FROM tblProviders
WHERE ProviderID IN (SELECT * FROM dbo.CSVToLIst(@CSV))
CSV to list function
CREATE FUNCTION dbo.CSVToList (@CSV varchar(3000))
RETURNS @Result TABLE (Value varchar(30))
AS
BEGIN
DECLARE @List TABLE
(
Value varchar(30)
)
DECLARE
@Value varchar(30),
@Pos int
SET @CSV = LTRIM(RTRIM(@CSV))+ ','
SET @Pos = CHARINDEX(',', @CSV, 1)
IF REPLACE(@CSV, ',', '') <> ''
BEGIN
WHILE @Pos > 0
BEGIN
SET @Value = LTRIM(RTRIM(LEFT(@CSV, @Pos - 1)))
IF @Value <> ''
INSERT INTO @List (Value) VALUES (@Value)
SET @CSV = RIGHT(@CSV, LEN(@CSV) - @Pos)
SET @Pos = CHARINDEX(',', @CSV, 1)
END
END
INSERT @Result
SELECT
Value
FROM
@List
RETURN
END
Upvotes: 0
Reputation: 1269973
The best way may be to munge the query string and use dynamic SQL. This allows the optimizer to compile the query for optimal execution. This approach is to insert the list of ids directly into the string. Of course, this can be a really bad idea if the list comes from user input, because this approach introduces the risk of SQL injection.
An alternative is to split the string. The most recent versions of SQL Server (2016+) have string_split()
(or you can find a UDF on the web quite easily):
SELECT p.*
FROM tblProviders p
WHERE p.ProviderID IN (SELECT string_split(@ProviderList, ',') )
Upvotes: 2