|
|
|
SSChampion
        
Group: General Forum Members
Last Login: 2 days ago @ 12:22 PM
Points: 10,571,
Visits: 11,871
|
|
|
|
|
|
Right there with Babe
      
Group: General Forum Members
Last Login: Tuesday, April 16, 2013 2:30 PM
Points: 797,
Visits: 88
|
|
I would like to know how to exclude "All" from multi-valued parameter and restrict users to choose not more than 5(for example) values in parameter list. If somebody knows the answer please help. Thank you.
|
|
|
|
|
Grasshopper
      
Group: General Forum Members
Last Login: 2 days ago @ 11:25 AM
Points: 18,
Visits: 135
|
|
We found a pretty easy to use and reliable way of doing this using a split function we built that returns the parameter array as a table. This way, we don't have to worry about dynamic SQL or SQL injection. Here's the function code and how we use it. The nice part about this function is that we can pass it whatever is needed for the delimiter. In this case, becuase SSRS returns multi-select parms as a comma seperated list, we use the comma. The following example will only return results from the main table where the category matches those selected in the parameters, whether it's 1 or 100 categories selected.
Example:
DECLARE @Categories VARCHAR(MAX) SET @Categories = 'VALUE1, VALUE2, VALUE3, ..., VALUE100' (this would be sent to the sproc by SSRS)
SELECT * FROM MainTable a inner join Reporting.dbo.ParmSplit(@Categories,',') b on a.Category = b.Items
-- ============================================= -- Description: Function splits a delimited string into -- seperate records and returns a table -- containing the individual values -- ============================================= CREATE FUNCTION [dbo].[ParmSplit](@String varchar(max), @Delimiter char(1)) RETURNS @Results TABLE (Items varchar(max)) AS BEGIN DECLARE @INDEX INT, @CNT INT DECLARE @VALUE varchar(max) SELECT @INDEX = 1, @CNT = 1 -- Initialize the variables WHILE @INDEX !=0 BEGIN SELECT @INDEX = CHARINDEX(@Delimiter,@STRING) -- Find the first split location IF @INDEX !=0 SELECT @VALUE = LEFT(@STRING,@INDEX - 1) -- Slice it up ELSE BEGIN SELECT @VALUE = @STRING SELECT @CNT = 10000 END INSERT INTO @Results(Items) VALUES(@VALUE) -- Store the results SELECT @STRING = RIGHT(@STRING,LEN(@STRING) - @INDEX) -- Remove used slice SELECT @CNT = @CNT + 1 -- See if we are done IF LEN(@STRING) = 0 BREAK IF @CNT > 8000 BREAK -- Limit to 8000 items END RETURN END
Addressing the last limit question, although not the cleaneast method, you could change the 8000 limit in the function (or make it a parmater of the function), and set the limit to 5, thereby limiting the selection to the first 5 selected in the list. This wouldn't be very clear for the users, but it would work to limit the result set.
|
|
|
|
|
SSC-Addicted
      
Group: General Forum Members
Last Login: Yesterday @ 4:02 AM
Points: 437,
Visits: 474
|
|
We struggled with this exact same issue and came up with a function which is used/called in the sp you are wanting to run;
Function: USE [LIVE] GO
/****** Object: UserDefinedFunction [dbo].[funcParseInputStringToTable] Script Date: 04/21/2009 13:43:36 ******/ SET ANSI_NULLS ON GO
SET QUOTED_IDENTIFIER ON GO
/*** BEGIN CREATE FUNCTION [dbo].[funcParseInputStringToTable] ***/
CREATE FUNCTION [dbo].[funcParseInputStringToTable] (@InputString nvarchar(255))
/* SPECIFY TEMPORARY TABLE*/ RETURNS @InputStringTable TABLE (InputValue nvarchar(255))
BEGIN /* DECLARE VARIABLES*/ DECLARE @Index1 AS nvarchar(255), @ParameterValue AS nvarchar(255) /* SET VARIABLES */ SET @Index1 = CHARINDEX(',', @InputString)
/* LOOP THROUGH THE INPUT STRING AND IDENTIFY THE INDIVIDUAL VALUES */ WHILE (@Index1 > 0 OR LEN(@InputString) > 0) BEGIN /* PARSE OUT EACH INDIVIDUAL PARAMETER AND STORE IN THE TEMPORARY TABLE */ IF @Index1 > 0 BEGIN SET @ParameterValue = Left(@InputString,@Index1 - 1) SET @InputString = Right(@InputString,Len(@InputString) - @Index1) END ELSE BEGIN SET @ParameterValue = @InputString SET @InputString = '' END
INSERT @InputStringTable (InputValue) VALUES(CAST(@ParameterValue AS nvarchar(255)))
/* PREPARE TO LOOP */ SET @Index1 = CHARINDEX(',', @InputString) END
/* RETURN THE VALUES FROM THE INPUT STRING */ RETURN END
Then by calling this function in the SP itself we were able to correct this issue with SSRS and Multivalued parameters. By using this method we kept the security and flexibility a function offers without touching XML etc.
|
|
|
|
|
Forum Newbie
      
Group: General Forum Members
Last Login: Thursday, October 04, 2012 9:33 PM
Points: 5,
Visits: 32
|
|
| We ran into problems with parsing the comma delimited string into a table because some data contains the comma delimiter. That is why we went to an XML approach.
|
|
|
|
|
Grasshopper
      
Group: General Forum Members
Last Login: Thursday, July 01, 2010 5:28 PM
Points: 12,
Visits: 20
|
|
I have been able to use multi-value parameters in a report and pass them to a stored procedure without doing any heavy lifting like this. You need to create a split function shown below and use the function and the IN statement in the WHERE clause and your done.
Report Parameter Name: FilterRegionId Data type: Integer Prompt: FilterRegionId Hidden: unchecked Internal: unchecked Multi-value: checked Allow null value: unchecked Allow blank value: checked (disabled checkbox) Available values: Non-queried Default values: Non-queried
Stored Procedure Parameter: @FilterRegionId AS varchar(max) WHERE Clause: WHERE ORG.OrganizationId IN(SELECT Item FROM dbo.Split(ISNULL(@FilterRegionId, ORG.OrganizationId), ','))
Split Function ------------------------
CREATE FUNCTION [dbo].[Split] /* This function is used to split up multi-value parameters */ ( @ItemList NVARCHAR(4000), @delimiter CHAR(1) ) RETURNS @IDTable TABLE (Item VARCHAR(50)) AS BEGIN DECLARE @tempItemList NVARCHAR(4000) SET @tempItemList = @ItemList
DECLARE @i INT DECLARE @Item NVARCHAR(4000)
SET @tempItemList = REPLACE (@tempItemList, @delimiter + ' ', @delimiter) SET @i = CHARINDEX(@delimiter, @tempItemList)
WHILE (LEN(@tempItemList) > 0) BEGIN IF @i = 0 SET @Item = @tempItemList ELSE SET @Item = LEFT(@tempItemList, @i - 1)
INSERT INTO @IDTable(Item) VALUES(@Item)
IF @i = 0 SET @tempItemList = '' ELSE SET @tempItemList = RIGHT(@tempItemList, LEN(@tempItemList) - @i)
SET @i = CHARINDEX(@delimiter, @tempItemList) END RETURN END
|
|
|
|
|
SSC Veteran
      
Group: General Forum Members
Last Login: Friday, November 12, 2010 1:45 PM
Points: 224,
Visits: 64
|
|
Alex
I am so glad you posted this article. It pertain specifically to an issue I am trying to resolve in two reports I am finalizing today. I am going to try what you have suggested here but am bot familar yet with CTE, the WHILE loop, or as Simon mentioned in the reply post a Split function but I will try each and hopefully come up with a solution....Thanks for the help!
Christina
|
|
|
|
|
Grasshopper
      
Group: General Forum Members
Last Login: Friday, November 13, 2009 7:18 AM
Points: 18,
Visits: 73
|
|
| But it feels so dirty doing string manipulation in a database to me with all that iterative processing... tally tables would be nicer, but quite a mindset jump.
|
|
|
|
|
Grasshopper
      
Group: General Forum Members
Last Login: 2 days ago @ 7:56 PM
Points: 22,
Visits: 239
|
|
| In real project I never used comma. I am using any non-keybord character, for example ASCII = 135. The comma was used for simplisity.
|
|
|
|
|
Grasshopper
      
Group: General Forum Members
Last Login: 2 days ago @ 7:56 PM
Points: 22,
Visits: 239
|
|
| Most of my fellow audience miss the point. For some reason your focus comes to how to parse a string, however this article how prevent array passing to stored procedure.
|
|
|
|