T-SQL Dynamic Where Clause and Nullable Columns

There are all kinds of very helpful articles online, like this one, explaining how to create a dynamic WHERE clause using COALESCE or ISNULL or CASE.  Generally, they describe something like this:

declare @FirstName NVarchar(50) = null
declare @LastName NVarchar(50) = null
declare @StreetAddress NVarchar(100) = null
declare @City NVarchar(50) = null
declare @JobNumber NVarchar(50) = ‘543216’

select e.FirstName, e.LastName, e.DeptID, a.StreetAddress, a.City,
a.StateID, a.ZipCode, j.JobName, j.JobNumber
from tblEmployee e
left join tblAddress a on e.EmployeeID = a.EmployeeID
left join tblJobs j on e.EmployeeID = j.EmployeeID
where e.FirstName = COALESCE(@FirstName, e.FirstName) AND
    e.LastName = COALESCE(@LastName, e.LastName) AND
    a.StreetAddress = COALESCE(@StreetAddress, a.StreetAddress) AND
    a.City = COALESCE(@City, a.City) AND
    j.JobNumber = COALESCE(@JobNumber, j.JobNumber)

And this works great as long as the columns in our WHERE clause all contain data.  However, any column with a NULL value will not be returned.  For instance, in the above example we are searching only by Job Number, so any record with a Job Number of 543216 should be returned.  But, if the StreetAddress field for any of those records is NULL, then they won’t be returned, even though there is a value of 543216 for the Job Number.

Why is this?  Because in our WHERE clause we are using the equal operator, and NULL can’t equal anything.  NULL isn’t a value – it just means UNKNOWN.  So NULL = NULL won’t return true, because what you’re really asking is “Does this unknown thing equal that unknown thing?”  And, of course, the answer to that is “Who knows?”  It can’t evaluate to true, so it must return false.

The solution, then, is to adjust the WHERE clause so that, if the values are NULL, we convert them to something known that we can compare.  If we add an ISNULL function to the column side of the equal sign, and add the same replacement value as the final value in the COALESCE function on the other side, as below, then the query should be able to evaluate and return all rows, even ones with NULL values.

declare @FirstName NVarchar(50) = null
declare @LastName NVarchar(50) = null
declare @StreetAddress NVarchar(100) = null
declare @City NVarchar(50) = null
declare @JobNumber NVarchar(50) = ‘543216’

select e.FirstName, e.LastName, e.DeptID, a.StreetAddress, a.City,
a.StateID, a.ZipCode, j.JobName, j.JobNumber
from tblEmployee e
left join tblAddress a on e.EmployeeID = a.EmployeeID
left join tblJobs j on e.EmployeeID = j.EmployeeID
where ISNULL(e.FirstName, ”) = COALESCE(@FirstName, e.FirstName, ”) AND
    ISNULL(e.LastName, ”) = COALESCE(@LastName, e.LastName, ”) AND
    ISNULL(a.StreetAddress, ”) = COALESCE(@StreetAddress, a.StreetAddress, ”) AND
    ISNULL(a.City, ”) = COALESCE(@City, a.City, ”) AND
    ISNULL(j.JobNumber, ”) = COALESCE(@JobNumber, j.JobNumber, ”)

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s