How would you do this - Solution

Published Sat, Mar 26 2005 13:59 | William

In the past, I've come up with some pretty nutty ways of handling this, most of which involved some version of COALESCING things - or, back in the day, Dynamic Sql.  However my homie/co-worker Jason Burton showed me the light on this one:

CREATE PROCEDURE [DBO].[usp_somesamplesearchprocedure]
     @FirstName     VARCHAR(8)     = NULL,
     @LastName      VARCHAR(20     = NULL,
     @CustomerID    VARCHAR(20)    = NULL,
     @DateOfBirth   SMALLDATETIME  = NULL
AS

    SELECT *
    FROM MyTableName
    WHERE
         (txt_First_Name LIKE @FirstName + '%OR @FirstName IS NULL)
    AND  (txt_Last_Name LIKE @LastName + '%OR @LastName IS NULL)
    AND  (n_CustomerID = @CustomerID OR @CustomerID IS NULL)
    AND  (dte_DateOfBirth = @DateOfBirth OR @DateOfBirth IS NULL)

By specifying a default value - you can just go ahead and pass in a search value from the client code if you want to used, or just pass in nothing if you don't.  From the client side, you can (tbFirstName.Text != string.Empty)? tbFirstName.Text : string.Empty;  (You'll need to do some conversion in your API or DALC implementation to take the String.Empty and convert it into a DbNull.Value but that's hardly worth mentioning.  We used Like in FirstName and LastName so that the requirement of similar matched names would be met, nothing too fancy about this.  The cool part is the parameter usage.  If there's a value, we restrict the columns based on each respective search criteria value.  If there isn't, we don't want to restrict on the field at all.  So if we passed in null for @FirstName (or didn't specify it), the value would be null so @FirstName IS Null would evaluate to true for each record.  The same logic holds for the other fields.  There are no non-deterministic functions being used here, so indexes can be used and the execution of the query will happen quite efficiently.

AFAIK, this is one of the better ways to handle this situation - but I'm not implying this is the only one.  Would definitely love to hear some feedback (either why they  like this way or why another way would be better) on this issue.

Filed under:

Comments

# William said on March 26, 2005 2:18 PM:

That's cool you can go back to making Kim happy now that I have seen the answer. ;)

# TrackBack said on March 26, 2005 2:47 PM:

# William said on March 26, 2005 2:57 PM:

First check for null, then for parameter:

http://blogs.x2line.com/al/articles/184.aspx

# William said on March 26, 2005 3:28 PM:

Anatoly: Yep, that's basically what I was thinking about it. From what I understand, if you use Coalesce or ISNULL instead, then you are using a deterministic function and since the values aren't known in advance, the execution is slowed. Can you think of any other 'cool things' to do when employing queries of this sort?

# William said on March 26, 2005 3:28 PM:

Andy - it's PMS time - All I do is piss Kim off until it's over ;-)

# William said on March 26, 2005 3:36 PM:

The problem with this approach (as I see it), is that the SP's query plan would vary quite a bit based on what parameters were supplied. I would run QA to see the differences. I think if performance was an issue, I would try to create a SP that called a more specifically tuned SP for specific likely case scenarios.

# William said on March 26, 2005 3:43 PM:

Bill - I appreciate your comments but I'm not sure I follow you. I'm not sure this is the 'best' way or close to it, it just seemed like an elegant way to handle it - but I run into this sort of thing all the time and have this is like the third generation approach I've come across. I'm definitely interested in coming up with something maintainable and solid.

If I understand you correctly, are you saying that you'd ideally have additional SP's for each of the likely scenarios (FirstName + LastName), (LastName + DOB), (DOB + CusomterID) etc covering the most likely permutations of search criteria and then basically branch out in the outer proc,calling the specific ones from there? Just thinking about it for a minute has actually given me a few ideas and now that I think about it - if performance is key- then I definitely see your point.

I'm gonna give it a try real quick and see what it looks like - you have my intrigued ;-) Thanks!

# William said on March 26, 2005 4:06 PM:

Bill: I agree, I made some tests a while ago:

http://blogs.x2line.com/al/archive/2004/03/01/189.aspx

The results were actually the same, but I'm not so sure now, maybe I need to retest it. I remeber I had an issue with isnull function once when it didn't return proper results out of the table, but I don't remember what.

# William said on March 26, 2005 7:24 PM:

I think what Mr. Vaughn is alluding to is parameter sniffing. I've run into this problem with our datamart.

The first time the sproc executes you pass in a FirstName and leave the other parameters NULL. SQL Server generates a great query plan to find the first name.

The second time you call the sproc you pass in a LastName and leave the other parameters NULL. Unfortunately, SQL reuses a cached query plan that was tuned for FirstName and, in the words of BV, you are pooched.

Another solution is to use 'WITH RECOMPILE', but a little overhead there.

# William said on March 26, 2005 8:22 PM:

Bill,
I'm a married guy I know all about PMS so take my 4 step plan to PMS bliss.

Step 1.) Buy her a big grocery bag of her favorite food and candies and give it to her.

Step 2.) Rent her a whole bunch of Lifetime style chic flicks.

Step 3.) Give her a day pass to a spa for the next day.

Step 4.) Go camping for 5 days. You'll have fun fishing and kicking back. She'll have fun with no dude around to get in her way and when you return everything is hunky dory again.

Works for me anyway.

Search

This Blog

Tags

Community

Archives

News

My other sites

Cool Stuff

Book Stuff

Security

ORM

Data Access

Funny Stuff

Compact Framework Stuff

Web Casts

My KnowledgeBase Articles

My MVP Profile

Design Patterns

Performance

Debugging

Remoting

My Fellow Authors

My Books

LINQ

Misc

Speech

Syndication

Email Notifications