Отправка одного и того же параметра дважды в exec - PullRequest
0 голосов
/ 21 сентября 2018

У меня есть простая хранимая процедура, подобная этой:

[dbo].[getStatusList]
    @Extended NVARCHAR(255) = 'Project Status',
    @Exclude NVARCHAR(255) = '',
    @All BIT = 0
AS
    SET NOCOUNT ON

    IF (@All = 0)
    BEGIN
        SELECT
            [GeneralKey],
            [Label]
        FROM 
            [General]
        WHERE 
            [Extended] = @Extended
            AND [Label] <> @Exclude
        ORDER BY
            [OrderID];
    END
    ELSE
    BEGIN
        IF (@All = 1)
        BEGIN
            SELECT
                0 AS [GeneralKey],
                'Any' AS [Label],
                0 AS [OrderID]
            UNION ALL
            SELECT
                [GeneralKey],
                [Label],
                [OrderID]
            FROM 
                [General]
            WHERE 
                [Extended] = @Extended
                AND [Label] <> @Exclude
            ORDER BY
                [OrderID];
        END
    END

Я хочу выполнить эту хранимую процедуру, отправив дважды @Extended параметр вроде:

exec getStatusList @Extended = 'title1' AND @Extended = 'title2'

Этоне возможно сделать что-то подобное на exec?Единственный способ решить эту проблему - добавить еще один параметр в хранимую процедуру?

Обновление

Как уже упоминалось в комментариях, я попробовал это:

CREATE OR ALTER PROCEDURE usp_Get_StatusListByDesignType
    -- Add the parameters for the stored procedure here
    @Extended NVARCHAR(MAX),
    @Exclude NVARCHAR(255) = '',
    @All BIT = 0
AS
    SET NOCOUNT ON

    IF (@All = 0)
    BEGIN
        DECLARE  @Parameter1 VARCHAR(50) 
        DECLARE  @Parameter2 VARCHAR(50) 

        ;WITH CTE AS 
        (
             SELECT 
                 *,
                 ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) rn
             FROM 
                 STRING_SPLIT (@Extended,',')
        ) 
        SELECT  
            @Parameter1 = MAX(CASE WHEN rn = 1 THEN VALUE END),
            @Parameter2 = MAX(CASE WHEN rn = 2 THEN VALUE END)
        FROM 
            CTE

        SELECT
            [GeneralKey], [Label]
        FROM 
            [General]
        WHERE 
            [Extended] IN (SELECT @Parameter1, @Parameter2)
            AND [Label] <> @Exclude
        ORDER BY
            [OrderID];
    END
    ELSE
    BEGIN
        IF (@All = 1)
        BEGIN
            SELECT
                0 AS [GeneralKey],
                'Any' AS [Label],
                0 AS [OrderID]
            UNION ALL
            SELECT
                [GeneralKey],
                [Label],
                [OrderID]
            FROM 
                [General]
            WHERE 
                [Extended]  IN (SELECT @Parameter1, @Parameter2)
                AND [Label] <> @Exclude
            ORDER BY
                [OrderID];
        END
        RETURN;

Но я получаю эту ошибку:

В списке выбора можно указать только одно выражение, если подзапрос не введен с EXISTS.

Ответы [ 2 ]

0 голосов
/ 21 сентября 2018

Этот метод:

exec getStatusList @Extended='title1' AND @Extended = 'title2'

он вообще не будет работать, так как параметр или переменная вообще могут содержать только одно значение и ничего более.Таким образом, вы не сможете сделать это, если не выполните процедуру сохранения дважды и не зададите параметры для каждого из них.Или вы можете использовать петли, чтобы сделать это.Но я не фанат петель и всегда советую избегать их как можно больше.

Метод, который я считаю подходящим для вашей ситуации, - это TVP с некоторыми изменениями самой процедуры сохранения.

Итак, вы передадите значения через запятую в @Extended, и из процедуры сохранения вы будете использовать IN() и NOT IN() вместо = и <>, это расширитэто иметь больше значений для сравнения, а не одно значение.

Затем вы можете использовать XML, чтобы разделить значения и превратить их в строки.

Итак, мы будем использовать это:

SELECT LTRIM(RTRIM(m.n.value('.[1]','varchar(8000)')))
FROM (
    SELECT CAST('<XMLRoot><RowData>' + REPLACE(@Extended,',','</RowData><RowData>') + '</RowData></XMLRoot>' AS XML) Extended
) D
CROSS APPLY Extended.nodes('/XMLRoot/RowData')m(n)

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

CREATE FUNCTION SplitToRows 
(   
    @Extended   VARCHAR(MAX)
)
RETURNS TABLE 
AS
RETURN 
(
    SELECT LTRIM(RTRIM(m.n.value('.[1]','varchar(8000)'))) Extended
    FROM (
        SELECT CAST('<XMLRoot><RowData>' + REPLACE(@Extended,',','</RowData><RowData>') + '</RowData></XMLRoot>' AS XML) Extended
    ) D
    CROSS APPLY Extended.nodes('/XMLRoot/RowData')m(n)
)

Теперь вы можете изменить процедуру сохранения следующим образом:

[dbo].[getStatusList]
                     @Extended NVARCHAR(255) = 'Project Status'
                    , @Exclude  NVARCHAR(255) = ''
                    , @All      BIT           = 0
AS
        SET NOCOUNT ON
        IF(@All = 0)
        BEGIN
            SELECT
                 [GeneralKey]
                , [Label]
                 FROM [General]
                 WHERE 
                     [Extended] IN( SELECT * FROM dbo.SplitToRows(@Extended) )
                 AND [Label] NOT IN( SELECT * FROM dbo.SplitToRows(@Exclude) ) 
                 ORDER BY
                        [OrderID];
        END
            ELSE
        BEGIN
            IF(@All = 1)
            BEGIN
               SELECT
                    0 AS [GeneralKey]
                   , 'Any' AS [Label]
                   , 0 AS [OrderID]
               UNION ALL
               SELECT
                    [GeneralKey]
                   , [Label]
                   , [OrderID]
                    FROM [General]
                    WHERE
                         [Extended] IN( SELECT * FROM dbo.SplitToRows(@Extended) )
                     AND [Label] NOT IN( SELECT * FROM dbo.SplitToRows(@Exclude) ) 
                    ORDER BY
                            [OrderID];
            END
        END

Теперь вы можете передавать несколько разделенных значений в @Extended и @Exclude одновременно, как это:

@Extended = 'title1, title2, title3'
@Exclude  = 'title5, title8'

, поэтому оба параметра будут использовать один и тот же метод.

0 голосов
/ 21 сентября 2018

Вы можете передать свой параметр как para1Val1,para1Val2..., связанный с , запятой.

, затем использовать функцию STRING_SPLIT, чтобы отделить его от , запятой, а затем получить параметр.

DECLARE @Extended varchar(max)='title1,titl2'

Вот простой

DECLARE @Extended varchar(max)='title1,titl2'

select *,row_number() over(order by (select NULL)) rn
from STRING_SPLIT (@Extended,',')

Затем вы можете установить параметры в SP.

объявить переменную параметров, а затем использовать row_number, чтобы сделать номер строки вашего параметра.

следующий шаг использовать условие агрегатная функция установить параметр в select предложении.

 declare  @parameter1 varchar(50) 
 declare  @parameter2 varchar(50) 
 ;with cte as (
   select *,row_number() over(order by (select NULL)) rn
   from STRING_SPLIT (@Extended,',')
 ) 
 select @parameter1 = MAX(case when rn = 1 then value end),
        @parameter2 = MAX(case when rn = 2 then value end)
 from cte

sqlfiddle

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...