Link to home
Start Free TrialLog in
Avatar of Declan Basile
Declan BasileFlag for United States of America

asked on

Creating a Dynamic Where Clause in a stored procedure in SQL Server

I want a stored procedure in SQL Server to have two optional parameters, @CUSTOMERID and @ASSEMBLYID, and return a recordset.  The procedure will only ever be called with just one of the two parameters specified.  If the first one is specified I want the WHERE cause of the recordset to be "WHERE CustomerId = @CUSTOMERID", and if the second parameter is specified I want the WHERE clause to be "WHERE AssemblyId = @ASSEMBLYID".  How can I dynamically create the where clause based on which parameter is provided?  Can I save the SQL to a string variable and then somehow execute the string variable to generate and return the recordset?
ASKER CERTIFIED SOLUTION
Avatar of Arun Murugan
Arun Murugan

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
where (
             (CustomerId = @CUSTOMERID OR @CUSTOMERID IS NULL)
           OR 
            (ASSEMBLYID = @ASSEMBLYID OR @ASSEMBLYID IS NULL)
           )

Open in new window


However this kind of approach does not generate efficient query plan for both conditions, better split in two queries.

@Arun Murugan - Your query will give wrong results
SOLUTION
Avatar of Scott Pletcher
Scott Pletcher
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Arun Murugan
Arun Murugan

@Najam - Just wanted to know Why? What is the difference you found between the WHERE clauses you and I have posted?
For any customerid other than @CUSTOMERID where AssemblyId  is null , that will be part of your result, which is not correct also other way around for AssemblyId
where (
             (CustomerId = @CUSTOMERID OR @CUSTOMERID IS NULL)
           AND 
            (ASSEMBLYID = @ASSEMBLYID OR @ASSEMBLYID IS NULL)
           )

Open in new window


will be the good one
Requirement doesn't state that. Let the author decide.
@Najam:

That is not true.  A NULL value is never "=" another value, even another NULL.  The first syntax is fine and much cleaner.

      WHERE
         CustomerId = @CUSTOMERID --a NULL CustomerID will NOT "=" a NULL @CUSTOMERID
         OR
         AssemblyId = @ASSEMBLYID --a NULL AssemblyId will NOT "=" a NULL @ASSEMBLYID

As noted, it could have performance issues being in the same proc, and therefore I stated that a recompile option ("hint") was also needed:

      WHERE
         CustomerId = @CUSTOMERID
         OR
         AssemblyId = @ASSEMBLYID
       OPTION (RECOMPILE)
@ScottPletcher & @Arun Murugan - I agree, my bad.
Avatar of Declan Basile

ASKER

What do you think about this solution?  Would I need an OPTION (RECOMPILE) if I did it this way?

DECLARE @SQL varchar(1000) 

SET @SQL = 'SELECT *.Assemblies FROM Assemblies WHERE ' 
IF @CUSOMTERID IS NOT NULL 
     SET @SQL = @SQL + 'CUSTOMERID = @CUSTOMERID '
ELSE
     SET @SQL = @SQL + 'ASSEMBLYID = @ASSEMBLYID '
END
    
EXEC(@SQL)

Open in new window

No.  And if you have more than two or three options, that is the preferred way to do it.  Except you must also deal with potential SQL injection, such as by using sp_executesql and providing the value of @CUSTOMER|@ASSEMBLYID only as parameter values, not strung directly into the query as any kind of text.
Thanks you.