Использование параметра tristate в хранимой процедуре

#sql #stored-procedures

Вопрос:

Как правильно это сделать? Например, как бы я изменил хранимую процедуру с помощью этой подписи:

 CREATE PROCEDURE dbo.MyProcedure
  @Param BIT = NULL
AS
  SELECT *
  FROM dbo.SomeTable T
  WHERE T.SomeColumn = @Param
 

Таким образом, предоставление @Param со значением 1 или 0 выполняет фильтр, но его указание или передача значения NULL не выполняет фильтрацию?

Ответ №1:

Предполагая, что NULL означает «все равно», затем используйте

 CREATE PROCEDURE dbo.MyProcedure 
   @Param BIT = NULL
AS
   SELECT *
   FROM dbo.SomeTable T
   WHERE T.SomeColumn = @Param OR @Param IS NULL
 

Ответ №2:

Есть более чем один способ. Вот один из них:

 SELECT *
  FROM dbo.SomeTable T
  WHERE T.SomeColumn = COALESCE(@Param, T.SomeColumn)
 

но это не будет включать строки, для которых T. SomeColumn равен НУЛЮ.

Следующая альтернатива будет включать эти строки:

 SELECT *
  FROM dbo.SomeTable T
  WHERE T.SomeColumn = @Param OR @Param IS NULL
 

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

Ответ №3:

Мне кажется, что самый чистый способ сделать это (в T-SQL) — это:

 SELECT * FROM TABLE WHERE column = ISNULL(@param, column)
 

Другие СУБД предпочли бы ОБЪЕДИНЯТЬСЯ вместо ISNULL.

Я думаю, что здесь более очевидно, в чем заключается цель, особенно когда вы начинаете добавлять другие предложения ИЛИ, и это также избавляет вас от необходимости в родителях при объединении с предложениями И.

В моем (очень) ограниченном тестировании также наблюдалось незначительное увеличение производительности при использовании ISNULL по сравнению с ИЛИ @p РАВНО НУЛЮ. Не то чтобы я выступаю за использование ISNULL из-за увеличения производительности (что в лучшем случае крайне незначительно и в худшем случае зависит от очень конкретных случаев), но приятно знать, что это не имеет значительных затрат. Честно говоря, я не уверен, почему это так или иначе изменило бы ситуацию, но план выполнения показывает разницу в стоимости фильтра примерно на 1%.