Выбрать все, если в хранимой процедуре параметр имеет значение NULL

Я хочу создать процедуру в SQL Server, которая будет выбирать и объединять две таблицы. Параметры @company, @from и @to всегда установлены, но @serie_type может иметь значение NULL. Если @serie_type не NULL, я просто хочу включить указанные типы, просто AND S.Type = @serie_type, но если @serie_type равно NULL, я хочу включить все типы, просто, просто не включайте оператор AND. Моя проблема в том, что я не знаю, будет ли установлен @serie_type, поэтому я хотел бы иметь что-то вроде этого:

/* pseudocode */
??? = AND (IF @serie_type IS NOT NULL S.Type = @serie_type)

Вот упрощенная версия процедуры:

CREATE PROCEDURE Report_CompanySerie
    @company    INT,
    @serie_type INT,
    @from       DATE,
    @to         DATE
AS
BEGIN
    SELECT
        *
    FROM Company C
        JOIN Series S ON S.Company_FK = C.Id
    WHERE C.Id = @company 
        AND S.Created >= @from
        AND S.Created <= @to
/* HERE IS MY PROBLEM */        
        AND ???
END
GO

Не хочу дублировать выделение, потому что реальное выделение намного больше этого.


person Andreas    schedule 22.09.2011    source источник
comment
см. это: stackoverflow.com/questions/2788391/optimal-search- запросы /   -  person KM.    schedule 22.09.2011


Ответы (4)


В этом нет необходимости AND (@serie_type IS NULL OR S.Type = @serie_type), поскольку в SQL Server есть встроенная функция, выполняющая эту логику за вас.

Попробуй это:

   .
   .
   AND  S.Type = isnull( @serie_type, S.Type)

Это возвращает

истина, если @serie_type имеет значение null, или результат @serie_type = S.Type, если @serie_type не равно нулю.

Из MSDN:

IsNull Заменяет NULL указанным значением замены.

ISNULL ( check_expression , replacement_value )

Значение check_expression возвращается, если оно не равно NULL; в противном случае, после неявного преобразования в тип check_expression возвращается значение replace_value, если типы отличаются.

person Preet Sangha    schedule 22.09.2011
comment
@jeroenh: похоже, вы ошибаетесь, ISNULL ( check_expression , replacement_value ) - возвращает тот же тип, что и check_expression. - person sll; 22.09.2011
comment
@jeroenh - Я редактировал этот ответ. Ты не прав. Я использую это в течение многих лет на SQL Server. - person Preet Sangha; 22.09.2011
comment
Вы абсолютно правы, сегодня узнали что-то новое. Действительно сожалею - person jeroenh; 22.09.2011
comment
@Preet Sangha: что ты имеешь в виду, говоря, что не нужно делать ...? Это не взлом, а конструкция ANSI SQL, в отличие от ISNULL, специфичной для T-SQL. Я не понимаю, почему не нужно делать приговор, есть ли побочные эффекты, которые вы имеете в виду, или что? Более того, с моей точки зрения условие с OR намного чище, чем ISNULL - person sll; 22.09.2011
comment
Привет, я имел в виду только то, что в SQL-сервер встроена более короткая конструкция. В конечном итоге все сводится к выбору, и я предпочитаю меньше кода большему. Если соответствие ANSI является требованием, тогда, конечно, мое утверждение неверно, но я не припоминаю, чтобы это был вопрос требований. - person Preet Sangha; 22.09.2011

Общий подход:

WHERE 
C.Id = @company          
AND S.Created >= @from         
AND S.Created <= @to 
AND  (@serie_type IS NULL OR S.Type = @serie_type)
person sll    schedule 22.09.2011
comment
Идеальный ответ, как проверить обе стороны. - person Vimal bhatt; 14.05.2013

Вы также можете использовать оператор case в предложении where

где e.ZoneId = случай, когда @ zoneid = 0, затем e.zoneid else @zoneid end

person Shreyas Maratha    schedule 13.02.2013
comment
Как я могу добавить условие меньше чем вместо = в S.Type = ISNULL (@ serie_type, S.Type) - person Ali Shahzad; 03.09.2013

Очень чистый подход будет определять ваш @serie_type как 0. Взгляните ниже:

CREATE PROCEDURE Report_CompanySerie
    @company    INT,
    @serie_type INT = 0,
    @from       DATE,
    @to         DATE
AS
BEGIN
    SELECT
        *
    FROM Company C
        JOIN Series S ON S.Company_FK = C.Id
    WHERE C.Id = @company 
        AND S.Created >= @from
        AND S.Created <= @to
/* HERE IS MY PROBLEM */        
        AND (@serie_type = 0 OR S.SerieType = @serie_type)
    END
GO
person SuicideSheep    schedule 31.12.2013