Those who post code snippets showing hand-built queries are frequently admonished to use bind variables. And for good reason: values supplied for bind variables are automagically quoted by the appropriate DBD. This eliminates the need for you to do database-specific character escaping within character strings. A cannonical example of this problem is:
$name = "O'Reilly"; $sth = $db->prepare("SELECT * FROM emp WHERE name = '$name'"); $sth->execute();
Here, the query that is constructed through interpolation has a syntax error. (Don't see it? Look again.)

Again, using bind variables:

$name = "O'Reilly"; $sth = $db->prepare("SELECT * FROM emp WHERE name = ?"); $sth->execute($name);
Here, $name is correctly escaped by the appropriate quote() method supplied by the DBD in use, and everyone is happy.

Query preparation separate from execution allows the database to plan out execution of the query, and save the plan for reuse by multiple executions. This can be a big win, but some databases don't support it. For those that don't, DBI pretends that they do, remembers the query, and when execute() is invoked, constructs the query (from correctly quoted bind variables), and ships it to the database for execution. This pretending is actually a good thing. It allows you to write portable code that will work regardless of whether the underlying RDBMS supports separate query preparation. Oracle supports separate query preparation. Sybase, MS SQL (through 7.0, at least), and MySQL (as of now) do not.

The Pitfall

The lurking horror in this scheme is that DBI doesn't actually parse queries. If you're using a database that doesn't support separate preparation and you hand DBI a query with bind parameters in the wrong places, it will dutifully hold on to it, fill in the pieces when you pass arguments to execute(), and everything will appear to work. Until you try to support a different database. Then, KaBOOM. If you're developing against MySQL with the intent of eventually supporting Oracle, then watch out.

You can only reliably bind values, not field or table names.

Database that plan query execution won't accept this, because they need table and field names to make their query execution plans. Without knowing table and field names, how can the database construct a plan that calls for using indexes that might be available? (Answer: It can't.)

Where people screw themselves with query binding is in trying to do something like this:

my $field = $old ? "olddata" : "newdata"; $sth = $db->prepare("SELECT * FROM ?"); $sth->execute($field);
This will work with several database, but only by an accidental side-effect of implementation. Move to Oracle, and KaBOOM. I've seen several code fragments like this in production code, and occassionally in PM posts.

If you want your code to survive migration to a new database, bind values in your queries, not field or table names.

Replies are listed 'Best First'.
Re: A DBI Query Binding Pitfall
by perrin (Chancellor) on Sep 13, 2002 at 18:42 UTC
    Simple (kinda) rule: placeholders replace literal values (like 7 or 'fudge'), that would vary each time a specific SQL statement is run. Changing the names of tables or columns (or adding and subtracting where clauses) creates new SQL statements, which must be prepared separately.
Re: A DBI Query Binding Pitfall
by lachoy (Parson) on Sep 13, 2002 at 18:05 UTC

    I never quite understood why people bind table names. The whole purpose of binding variables is to deal with quoting issues, and, in more advanced databases, prepare a query plan that will allow subsequent execute() calls to execute faster. Table names don't have quoting problems, and you certainly can't create a query plan without a table name.

    Do you know why people do this? Is it just exuberance with a particular way of doing things?

    Chris
    M-x auto-bs-mode

      I never quite understood why people bind table names. Do you know why people do this? Is it just exuberance with a particular way of doing things?

      I suspect it's because they've been told that hand-build queries are risk, and binding is good, but they don't understand the limitations.

      It's sort of like being told "Go that way" without being told "But look out for that puddle" or knowing to look out for one.

Re: A DBI Query Binding Pitfall
by mpeppler (Vicar) on Sep 19, 2002 at 09:56 UTC
    Oracle supports separate query preparation. Sybase, MS SQL (through 7.0, at least), and MySQL (as of now) do not.
    Just a small correction - Sybase does support separate query preparation natively, and DBD::Sybase does as well.

    Michael