views:

1650

answers:

5

I've got a search screen on which the user can specify any combination of first name, last name, semester, or course. I'm not sure how to optimally code the SQL Server 2005 stored procedure to handle these potentially optional parameters. What's the most efficient way? Separate procedures for each combination? Taking the items in as nullable parms and building dynamic SQL?

A: 

I would do it with sp_executesql because the plan will be cached just for the first pattern, or the first set of conditions.

Take a look at this TechNet article:

*sp_executesql can be used instead of stored procedures to execute a Transact-SQL statement many times when the change in parameter values to the statement is the only variation. Because the Transact-SQL statement itself remains constant and only the parameter values change, the SQL Server query optimizer is likely to reuse the execution plan it generates for the first execution.*

muerte
If you use sp_executesql, you need to make sure that you do not introduce any SQL injection problems.
Redbeard 0x0A
So your answer is "dynamic sql" then.
Crescent Fresh
Not necessarily - the question was for the stored procedure solution, and there might be some additional logic before sp_executesql. Bottom line, the real answer is that one should try to avoid checking for NULL values for each parameter, at least for performance reasons.
muerte
+4  A: 

I'd set each parameter to optional (default value being null)

and then handle it in the WHERE....

FirstName=ISNULL(@FirstName,FirstName)
AND
LastName=ISNULL(@LastName,LastName)
AND
SemesterID=ISNULL(@SemesterID,SemesterID)

That'll handle only first name, only last name, all three, etc., etc.

It's also a lot more pretty/manageable/robust than building the SQL string dynamically and executing that.

Kevin Fairchild
I agree, it is more readable, but the plan will be cached just for the first pattern, so if performance is issue, executing dynamic sql might be better solution.
muerte
+ 1 I would do the same, but use the (@Paremeter is null or Column = @Paremeter) syntax
cmsjr
Until you start going to the direction of parameters determining the joins you use, this method is still fairly good on performance, @muerte And, as a general rule, performance is expendable -- maintainability/readability isn't ;)
Kevin Fairchild
You might try optimizing a bit and getting the NULL out of the where clause. From what I understand (and this might be dated information), the MS SQL Query plan processor never reuses a cached query plan when a NULL parameter appears in a where clause.
Robert C. Barth
A: 

Was just posting the same concept as Kevin Fairchild, that is how we typically handle it.

You could do dynamic sql in your code to create the statement as required but if so you need to watch for sql injection.

schooner
A: 

As muerte points out, the plan will be cached for the first set of parameters. This can lead to bad performance when its run each subsequent time using alternate parameters. To resolve that use the WITH RECOMPILE option on the procedure.

+2  A: 

The best solution is to utilize sp_execute_sql. For example:

--BEGIN SQL
declare @sql nvarchar(4000)

set @sql = 
'select * from weblogs.dbo.vwlogs 
where Log_time between @BeginDate and @EndDate'
+ case when @UserName is null then '' else 'and client_user = @UserName' end

sp_execute_sql
@sql
, @params = '@UserName varchar(50)'
, @UserName = @UserName
--END SQL

As muerte mentioned, this will have a performance benefit versus exec()'ing a similar statement.

Cadaeic
How would this change if I had the following parameters:1. Lastname (LIKE operator)2. Course (no LIKE)3. Section (no LIKE)With all intact, it would be:SELECT * FROM courseEnrollment where Lastname like 'Bob%' and course='100' and section='001'
Caveatrob
Alter the "client_user = @UserName" portion to reflect what actual condition you want added to your query.
Cadaeic