0

I am trying to make a query that does the following: I have columns in my Items database, and these columns are called Title, AuthorName and ItemType. I want to do the following in my query: User enters AuthorName, Title and selects ItemType from the dropdown list. User may leave AuthorName or Title boxes empty. Even if he for example does not fill AuthorName part, if an item is found with specified ItemType and specified Title i show it in results. Similarly Title may be left empty, in this case the item with the specified AuthorName is listed in results list. Here is my query:

SELECT  *
FROM    [Items]
WHERE   ( ( ( [Title] LIKE '%' + @Title + '%' )
            AND ( [ItemType] = @ItemType )
          )
          OR ( ( [AuthorName] LIKE '%' + @AuthorName + '%' )
               AND ( [ItemType] = @ItemType )
             )
        )

But when AuthorName or Title is left empty, no results are found. Can anyone help?

Thanks

2
  • Define Empty. Does empty mean a zero length string or null? Commented May 30, 2013 at 15:10
  • 1
    Just be aware that leading wildcards like % prevent the database from using any indexes it may have on that column, and force it to do a table scan. Trailing wildcards are fine. Only leading wildcards are a problem. If the table is large, any search you do this way will be slow. Simply a fact of life. Commented May 30, 2013 at 15:14

4 Answers 4

2
Select ...
From Items
Where ( @Title Is Null Or Title Like '%' + @Title + '%' )
    And ( @AuthorName Is Null Or AuthorName Like '%' + @AuthorName + '%' )
    And ItemType = @ItemType

In ASP.NET, you should be checking your form values against string.IsNullOrEmpty and if true, sending DBNull.Value to your parametrized query instead of an empty string.

If you insist on passing an empty string for your parameters (which isn't preferred) then the query needs to check for empty strings:

Select ...
From Items
Where ( Len(@Title) = 0 Or Title Like '%' + @Title + '%' )
    And ( Len(@AuthorName) = 0 Or AuthorName Like '%' + @AuthorName + '%' )
    And ItemType = @ItemType

In SQL Server, the Len function will ignore spaces. If you really wanted to go crazy and do all your checking in the query (which again isn't recommended) then you would want to account for your parameters being empty strings, all spaces or nulls:

Select ...
From Items
Where ( Len(Coalesce(@Title,'')) = 0 Or Title Like '%' + @Title + '%' )
    And ( Len(Coalesce(@AuthorName,'')) = 0 Or AuthorName Like '%' + @AuthorName + '%' )
    And ItemType = @ItemType
Sign up to request clarification or add additional context in comments.

Comments

1

I wrote a whole tutorial on this in my code blog at code.scottshipp.com. A full download of the code in that tutorial is available. It shows how to set it up as a stored procedure but also goes into detail on how to construct the where clause in your query. So it covers both instances. It may be easier for you to go the Stored Procedure route though, so you may want to give it a read.

The thing to keep in mind is that there are various methods to do this but there are some "gotcha's" also that will make your code seem to work in some situations and not others if you use something like the ISNULL function.

Instead, in general, I would recommend the following:

Add the following snippet to any part of your where clause you expect to sometimes be blank:

    OR SomeParam IS NULL

Also, it is good for readability to put parentheses around the entire thing. Do this for each parameter that you think may at some point be blank. This means for instance, that your select statement will become:

SELECT  *
FROM    [Items]
WHERE   ( ( ( [Title] LIKE '%' + @Title + '%' OR [Title] IS NULL )
        AND ( [ItemType] = @ItemType OR [ItemType] IS NULL )
      )
      OR ( ( [AuthorName] LIKE '%' + @AuthorName + '%' OR [AuthorName] IS NULL)
           AND ( [ItemType] = @ItemType OR [ItemType] IS NULL )
         )
    )

Comments

1

Please try this

  SELECT  *
FROM    [Items]
WHERE   ( ( ( [Title] LIKE CASE WHEN ISNULL(@Title,'')='' THEN [Title] ELSE '%' + @Title + '%' END )
            AND ( [ItemType] = @ItemType )
          )
          OR ( ( [AuthorName] LIKE CASE ISNULL(@AuthorName,'')='' THEN [AuthorName] ELSE '%' + @AuthorName + '%' END)
               AND ( [ItemType] = @ItemType )
             )
        )

This will help. This will run even is you dont pass Title or Authorname.

1 Comment

Thanks, but it gives an error saying that an expression of non boolean type specified in context where a condition is expected, near 'THEN'.
1

Try something like this:

SELECT  *
FROM    [Items]
WHERE   ([ItemType] = @ItemType)
        AND ([Title] LIKE '%' + @Title + '%' OR @Title IS NULL)
        AND ([AuthorName] LIKE '%' + @AuthorName + '%' OR @AuthorName IS NULL)

Just be sure to pass in NULL values (System.DBNull.Value) when AuthorName or Title is empty.

UPDATE:

Assuming AuthorName and Title are passed to your code-behind as empty strings when they are "not selected", you can do something like this (where authorName and title are Strings passed to your code-behind):

VB:

cmd.Parameters.Add("AuthorName", SqlDbType.VarChar, 50).Value = IIf(authorName.length > 0, authorName, System.DBNull.Value)
cmd.Parameters.Add("Title", SqlDbType.VarChar, 50).Value = IIf(title.length > 0, title, System.DBNull.Value)

C#:

cmd.Parameters.Add("AuthorName", SqlDbType.VarChar, 50).Value = (authorName.length > 0 ? authorName : System.DBNull.Value);
cmd.Parameters.Add("Title", SqlDbType.VarChar, 50).Value = (title.length > 0 ? title : System.DBNull.Value);

1 Comment

That did not work, i am not sure how to be sure to pass in NULL values (System.DBNull.Value) when AuthorName or Title is empty. Can this be a problem? How can i pass NULL values?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.