tags:

views:

236

answers:

3

I want to be able to pass something into an SQL query to determine if I want to select only the ones where a certain column is null. If I was just building a query string instead of using bound variables, I'd do something like

 if ($search_undeleted_only)
 {
     $sqlString .= " AND deleted_on IS NULL";
 }

but I want to use bound queries. Would this be the best way?

 my $stmt = $dbh->prepare(...
     "AND (? = 0 OR deleted_on IS NULL) ");
 $stmt->execute($search_undeleted_only);
+3  A: 

Yes; a related trick is if you have X potential filters, some of them optional, is to have the template say " AND ( ?=-1 OR some_field = ? ) ", and create a special function that wraps the execute call and binds all the second ?s. (in this case, -1 is a special value meaning 'ignore this filter').

Update from Paul Tomblin: I edited the answer to include a suggestion from the comments.

SquareCog
That's good, but put it the other way around (the ?=-1 part first), since many SQL databases where clauses short circuit (meaning, it won't bother evaluating the subsequent part of an OR statement if the first part is true since there's no way it will evaluate to anything but true).
Robert C. Barth
Robert is right, `?=-1` should go first
SquareCog
I hope you guys don't mind, but I'm going to edit your answer to put the ?=-1 first just to make the answer better.
Paul Tomblin
By the way, there is some really good information about the query optimization in Bill Karwin's answer. I wish I could accept them both.
Paul Tomblin
+1  A: 

I think that's a reasonable approach. It follows the normal filter pattern nicely and should give good performance.

Michael Haren
+2  A: 

So you're relying on short-circuiting semantics of boolean expressions to invoke your IS NULL condition? That seems to work.

One interesting point is that a constant expression like 1 = 0 that did not have parameters should be factored out by the query optimizer. In this case, since the optimizer doesn't know if the expression is a constant true or false until execute time, that means it can't factor it out. It must evaluate the expression for every row.

So one can assume this add a minor cost to the query, relative to what it would cost if you had used a non-parameterized constant expression.

Then combining with OR with the IS NULL expression may also have implications for the optimizer. It might decide it can't benefit from an index on deleted_on, whereas in a simpler expression it would have. This depends on the RDBMS implementation you're using, and the distribution of values in your database.

Bill Karwin
@Bill, that's really great info about the query optimization, and I wish I could accept both yours and Dmitriy's answers.
Paul Tomblin
No worries! I'm glad it was useful.
Bill Karwin