I have a report im creating in SSRS (2008) and the data for the report is coming from a stored procedure in MS SQL.
I want to have a multiple value parameter (done this
Create this function in your database:
USE [YourDatabase]
GO
/****** Object: UserDefinedFunction [dbo].[SplitListToTable] Script Date: 5/21/2018 8:13:29 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
--==========================================================
-- Author: Gugg
-- Created: 2015-10-06
-- Description: Converts a delimited string into a table of values. Based heavily on code from this url:
-- https://social.msdn.microsoft.com/Forums/sqlserver/en-US/0ead7ceb-3fdd-4625-aa82-1d4195f984b1/passing-multivalue-parameter-in-stored-procedure-ssrs
-- Modification History:
--===========================================================
CREATE FUNCTION [dbo].[SplitListToTable]
(
@List NVARCHAR(2000) ,
@SplitOn NVARCHAR(5)
)
RETURNS @RtnValue TABLE
(
Id INT IDENTITY(1, 1) ,
Value NVARCHAR(100)
)
AS
BEGIN
WHILE ( CHARINDEX(@SplitOn, @List) > 0 )
BEGIN
INSERT INTO @RtnValue
( Value
)
SELECT Value = LTRIM(RTRIM(SUBSTRING(@List, 1, CHARINDEX(@SplitOn, @List) - 1)));
SET @List = SUBSTRING(@List, CHARINDEX(@SplitOn, @List) + LEN(@SplitOn), LEN(@List));
END;
INSERT INTO @RtnValue
( Value )
SELECT Value = LTRIM(RTRIM(@List));
RETURN;
END;
GO
Then you can parse your parameter like this:
SELECT *
FROM YourDatabase.dbo.YourTable
WHERE YourColumn IN(SELECT value FROM dbo.SplitListToTable(@YourParameter, ','))
I feel your pain, we had the same issue when using SSRS with SP's. You do indeed need to split out the values you are passing to the stored procedure.
In your stored Procedure SQL is expecting;
Alias.Field1 IN (@RC)
Which compiles down to
Alias.Field1 IN ('Value1','Value2,'Value3')
However, SSRS will pass the parameter values as one long string (why MS did is beyond me) and will end up being this
Alias.Field1 IN ('Value1,Value2,Value3')
Which, as you correctly pointed out, you have zero control over. So you need to use a Split Strings function. Aaron Bertrand did a great blog post on this one over at SQLPerformance.com which gives you the pros and cons of each method based on the size of your database. We used the SplitStrings CTE as it gave the best performance for the size of most of our DBs.
Here is the function;
CREATE FUNCTION [dbo].[fn_SplitStringsCTE]
(
@List NVARCHAR(MAX),
@Delimiter NVARCHAR(255)
)
RETURNS @Items TABLE (Item NVARCHAR(4000))
WITH SCHEMABINDING
AS
BEGIN
DECLARE @ll INT = LEN(@List) + 1, @ld INT = LEN(@Delimiter);
WITH a AS
(
SELECT
[start] = 1,
[end] = COALESCE(NULLIF(CHARINDEX(@Delimiter,
@List, 1), 0), @ll),
[value] = SUBSTRING(@List, 1,
COALESCE(NULLIF(CHARINDEX(@Delimiter,
@List, 1), 0), @ll) - 1)
UNION ALL
SELECT
[start] = CONVERT(INT, [end]) + @ld,
[end] = COALESCE(NULLIF(CHARINDEX(@Delimiter,
@List, [end] + @ld), 0), @ll),
[value] = SUBSTRING(@List, [end] + @ld,
COALESCE(NULLIF(CHARINDEX(@Delimiter,
@List, [end] + @ld), 0), @ll)-[end]-@ld)
FROM a
WHERE [end] < @ll
)
INSERT @Items SELECT [value]
FROM a
WHERE LEN([value]) > 0
OPTION (MAXRECURSION 0);
RETURN;
END
GO
And here is how you implement it in your Stored Procedure;
AND (Alias.Field1 IN (SELECT Item FROM [dbo].[fn_SplitStringsCTE](@RC,',')))
As for passing NULLs to the Stored Procedure, this is also something we wanted to do but instead decided to use the following, and then adding a value to you SSRS parameter that passes 'All Values', it was a nice catch-all for us when we wanted to return all the values of that parameter, but if you have NULLs in your dataset they will also need to be handled.
AND (@RC = 'All Values' OR Alias.Field1 IN (SELECT Item FROM [dbo].[fn_SplitStringsCTE](@RC,',')))