views:

614

answers:

3

I'm writing a fairly complex stored procedure to search an image library.

I was going to use a view and write dynamic sql to query the view, but I need to use a full text index, and my view needs outer joins (http://stackoverflow.com/questions/1094695/ms-sql-2005-full-text-index-on-a-view-with-outer-joins)

So, I'm back to a stored procedure.

I need to search on (all optional):

  • a general search query that uses the full text index (or no search terms)
  • one or more categories (or none)
  • a single tag (or none)

Is there a way to do a conditional FREETEXT in the 'WHERE' clause? The query may be empty, in which case I want to ignore this, or just return all FTI matches.

...AND FREETEXT(dbo.MediaLibraryCultures.*, '"* "') doesn't seem to work. Not sure how a case statement would work here.

Am I better off inserting the category/tag filter results into a temp table/table variable, then joining the FTI search results? That way I can only do the join if the search term is supplied.

Thoughts?

A: 

You could add a check for the empty search string like

where ...
AND (FREETEXT(dbo.MediaLibraryCultures.*, @FreeTextSearchFor) OR @FreeTextSearchFor = '')

(I have a feeling that freetext searches can't have null passed into them, so I'm comparing to an empty string)

If the term to search for is empty, the whole clause will evaluate to true, so no restrictions will be applied (by this clause) to the rows returned, and of course since its a constant being compared to a variable - I would think the optimizer would come into play and not perform that comparison for each row.

Tetraneutron
Nope, the predicate can't be null or empty.
ScottE
A: 

Hmm, I thought there was no short-circuiting in sql server?

AND (@q = '' OR FREETEXT(dbo.MediaLibraryCultures.*, @q))

seems to work just fine!

Strangely, the full text scan is still part of the execution plan.

ScottE
Its interesting that the full text search is in the execution plan - I thought the query optimizer would see the @q and '' both as constants and exclude the whole check (making any short circuiting irrelevant as it wouldn't even be included in the end query) but I guess since a query can affect the variable for each row the optimizer can't assume this. I'm also interested to find out if the full text search in the execution plan takes up much time?Also if this is the answer you are running with, mind marking it as the accepted answer?
Tetraneutron
I also ran a little test to see if SQL does short circuit, the results are a little confusingcreate table #tempShort (a int)select * from #tempShort where (1 / 0) > 1select * from #tempShort where 1 = 1 or (1 / 0) > 1select * from #tempShort where (1 / 0) > 1 or 1 = 1drop table #tempShortif it did short circuit I would expect the first and third selects to fail with the second succeeding, but both the second and third succeed, draw what conclusions as you will.
Tetraneutron
Yes, I'm going with this answer. I can't mark it as accepted yet - have to wait 48 hours. The execution plan showed the same amount of time for the fti step regardless of whether @q was empty or not. It's not a good test in my case, however, as the FTI is currently quite small.
ScottE
A: 

I know it's a year later and a newer version of SQL but FYI...

I am using SQL Server 2008 and have tried to short circuit using

AND ( @searchText = '' OR freetext(Name, @searchText))

and I receive the message "Null or empty full-text predicate" when setting @searchText = ''. I guess something in 2008 has changed that keeps short circuiting from working in this case.

jpc
Interesting. We're still running 2005, thankfully.
ScottE