Solution:
The best way to handle such optional parameters is to use dynamic SQL and built the query on the fly. Something like....
CREATE PROCEDURE myProc
@Param1 VARCHAR(100) = NULL
,@Param2 VARCHAR(100) = NULL
,@Param3 VARCHAR(100) = NULL
,@ListParam VARCHAR(100) = NULL
--, etc etc...
AS
BEGIN
SET NOCOUNT ON;
Declare @Sql NVARCHAR(MAX);
SET @Sql = N' SELECT *
FROM TableName
WHERE 1 = 1 '
-- add in where clause only if a value was passed to parameter
+ CASE WHEN @Param1 IS NOT NULL THEN
N' AND SomeColumn = @Param1 ' ELSE N'' END
-- add in where clause a different variable
-- only if a value was passed to different parameter
+ CASE WHEN @Param2 IS NOT NULL THEN
N' AND SomeOtherColumn = @Param3 ' ELSE N'' END
-- List Parameter used with IN clause if a value is passed
+ CASE WHEN @ListParam IS NOT NULL THEN
N' AND SomeOtherColumn IN (
SELECT Split.a.value(''.'', ''VARCHAR(100)'') IDs
FROM (
SELECT Cast (''<X>''
+ Replace(@ListParam, '','', ''</X><X>'')
+ ''</X>'' AS XML) AS Data
) AS t CROSS APPLY Data.nodes (''/X'') AS Split(a) '
ELSE N'' END
Exec sp_executesql @sql
, N' @Param1 VARCHAR(100), @Param2 VARCHAR(100) ,@Param3 VARCHAR(100) ,@ListParam VARCHAR(100)'
, @Param1
, @Param2
,@Param3
, @ListParam
END
Problem with Other approach
There is a major issue with this other approach, you write your where clause something like...
WHERE ( ColumnName = @Parameter OR @Parameter IS NULL)
The Two major issues with this approach
1) you cannot force SQL Server to check evaluate an expression first like if @Parameter IS NULL
, Sql Server might decide to evaluate first the expression ColumnName = @Parameter
so you will have where clause being evaluated even if the variable value is null.
2) SQL Server does not do Short-Circuiting (Like C#), even if it decides to check the @Parameter IS NULL
expression first and even if it evaluates to true, SQL Server still may go ahead and evaluating other expression in OR
clause.
Therefore stick to Dynamic Sql for queries like this. and happy days.