Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

this works.

my $sth = $dbh->prepare( 'select * from mytable order by col_3' ) or die DBI->errstr; $sth->execute() or die DBI::errstr; while( my $aref = $sth->fetch ) { print "@$aref"; }

this doesn't?

my $sth = $dbh->prepare( 'select * from mytable order by ?' ) or die DBI->errstr; $sth->execute( 'col_3' ) or die DBI::errstr; while( my $aref = $sth->fetch ) { print "@$aref"; }

Replies are listed 'Best First'.
Re: DBI order by clause and placeholders
by pokki (Monk) on Jun 10, 2013 at 18:37 UTC

    It's got nothing to do with Perl, though.

    In general, the only places you're allowed to have placeholders are places where you'd have column values. This does not include table names and column names.

    Assuming a table "blah" with columns "foo", "bar", "baz", you can't do the following either:

    my $sth = $dbh->prepare('SELECT foo, bar, baz FROM ? WHERE ...'); $sth->execute('blah');

    You'll have to fall back to building queries by string manipulation, if you really really need dynamic table names.

    You can do this but it won't return what you expect:

    my $sth = $dbh->prepare('SELECT foo, bar, ? FROM blah WHERE foo = 1 AN +D bar = 2'); $sth->execute('baz');

    It'll just fetch 1, 2, and the literal string "baz". Consult your database server's documentation for more information.

    The MySQL doc in particular says:

    Within the statement, ? characters can be used as parameter markers to indicate where data values are to be bound to the query later when you execute it. The ? characters should not be enclosed within quotation marks, even if you intend to bind them to string values. Parameter markers can be used only where data values should appear, not for SQL keywords, identifiers, and so forth.
Re: DBI order by clause and placeholders
by stephen (Priest) on Jun 10, 2013 at 17:24 UTC

    Parameters passed in via placeholders are assumed to be string literals and are autoquoted. So the second example would translate to something like:

    select * from mytable order by 'col_3'

    That doesn't really make sense.

    stephen

Re: DBI order by clause and placeholders
by dsheroh (Monsignor) on Jun 11, 2013 at 09:27 UTC
    Meditate for a moment upon the distinct functions of prepare and execute.

    prepare examines the structure of the query and constructs a plan for how it shall ultimately be processed.

    execute runs that plan, providing any data values that may be needed to do so.

    Changing an order by clause affects the way that the query is processed. It is a structural change, not a changed data value. It must, therefore, be specified at the prepare stage, when the structure of the query is established, not at the execute stage.

Re: DBI order by clause and placeholders
by Neighbour (Friar) on Jun 11, 2013 at 06:48 UTC
    For MySQL (not T-SQL or Oracle) there's an extra trick. You can use ? as a placeholder for a comma separated list:
    SELECT * FROM table WHERE foo IN (?)
    Which you then feed a string like join(',', @values).