хранимая процедура многозначного параметра ssrs - PullRequest
0 голосов
/ 21 мая 2018

У меня есть отчет, который я создаю в SSRS (2008), и данные для отчета поступают из хранимой процедуры в MS SQL.

Я хочу иметь параметр с несколькими значениями (это делается миллион раз)но не с SP)

Я создал параметр на основе запроса, поставил галочку в разрешении нескольких значений и изменил SP для использования оператора IN (поэтому IN (@Param))

Это просто не будет работать SQL Server Profiler показать, что это передается

@RC=N'1,2'

Если я выберу одно значение, он работает (возвращая одно значение)

Я видел сообщения о разделении соединения и яЯ пробовал все это безрезультатно.

Любые идеи (конечно, это просто !!) В идеале мне бы хотелось иметь возможность вернуть NULL тоже (или это слишком много, чтобы спросить?

Спасибо всем

Ответы [ 2 ]

0 голосов
/ 21 мая 2018

Я чувствую вашу боль, у нас была та же проблема при использовании SSRS с SP.Вам действительно нужно разделить значения, которые вы передаете в хранимую процедуру.

В вашей хранимой процедуре SQL ожидает;

 Alias.Field1 IN (@RC) 

, который компилируется до

Alias.Field1 IN ('Value1','Value2,'Value3')

Тем не менее, SSRS передаст значения параметров в виде одной длинной строки (почему MS сделал это за меня) и в итоге получит это

Alias.Field1 IN ('Value1,Value2,Value3')

Который, как вы правильно указали, имеет нулевой контрольнад.Поэтому вам нужно использовать функцию Split Strings.Об этом Аарон Бертран написал отличный пост в блоге SQLPerformance.com , в котором рассказывается о плюсах и минусах каждого метода в зависимости от размера вашей базы данных.Мы использовали SplitStrings CTE, поскольку он дал наилучшую производительность для размера большинства наших БД.

Вот функция;

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 (Alias.Field1 IN (SELECT Item FROM [dbo].[fn_SplitStringsCTE](@RC,',')))

Что касается передачи значений NULL в хранимую процедуру, мы тоже хотели это сделать, но вместо этого решили использовать следующее, а затем добавить значение в свой параметр SSRS, который передает «Все значения».', это была хорошая ловушка для нас, когда мы хотели вернуть все значения этого параметра, но если у вас есть NULL в вашем наборе данных, они также должны быть обработаны.

AND (@RC = 'All Values' OR Alias.Field1 IN (SELECT Item FROM [dbo].[fn_SplitStringsCTE](@RC,',')))
0 голосов
/ 21 мая 2018

Создайте эту функцию в вашей базе данных:

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

Затем вы можете проанализировать ваш параметр следующим образом:

SELECT *
FROM YourDatabase.dbo.YourTable
WHERE YourColumn IN(SELECT value FROM dbo.SplitListToTable(@YourParameter, ','))
...