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

Can someone help me out with this? My mysql skills are less than adequate.
$sth = $dbh->prepare("SELECT * FROM $pictures_table WHERE stats="2" AN +D poster_name = "param('name')" ASC ");
it says the error is anywhere from the SELECT to stats="2". Stats is a column name

Replies are listed 'Best First'.
Re: single error with a dbh prepare
by davorg (Chancellor) on May 17, 2006 at 15:16 UTC

    Check your quotes. You are using double quotes within a double-quoted string - and that's never going to work. I recommend switching to qq().

    Also, you need to use the concaternation operator and more quotes to include the parameter value in the string.

    Oh. And your order clause isn't right.

    $sth = $dbh->prepare(qq( SELECT * FROM $pictures_table WHERE stats="2" AND poster_name = ') . param('name') . qq(' ORDER BY poster_name ASC));

    Actually, it might be easier to use a placeholder to insert the parameter. That way you don't need to worry about the quoting.

    $sth = $dbh->prepare(qq( SELECT * FROM $pictures_table WHERE stats="2" AND poster_name = ? ORDER BY poster_name ASC)); $sth->execute(param('name'));
    --
    <http://dave.org.uk>

    "The first rule of Perl club is you do not talk about Perl club."
    -- Chip Salzenberg

      does mysql accept dblquotes for stats="2" or does it have to be single stats='2' ? Might as well bind that anyways w/ stats = ? and $sth->execute(2, param('name')) so there's no quoting at all..

        does mysql accept dblquotes for stats="2" or does it have to be single stats='2'?

        Yes, it accepts both.

        Oh, btw, just go to http://www.mysql.com/ and download any stable version and try it out, works on most platforms, is free of charge (in that circumstance) and easy to install (5-10 minutes) and get up to speed.

        Cheers, Sören

Re: single error with a dbh prepare
by McDarren (Abbot) on May 17, 2006 at 15:32 UTC
    As davorg points out, your immediate problem is that your quoting is screwed up.

    However, there are couple of other things I'll point out - which you can either take on board, or ignore completely ;)

    Update: As has been pointed out below, placeholders are not appropriate for column names (which don't need to be quoted anyway). Have updated my example accordingly.

    1. It's best to try and avoid "SELECT *", and instead explicitly select the columns that you need. You never know when somebody might come along and add a few colums without you knowing.

    2. Use placeholders!! Especially in CGI scripts, which this one obviously is. Instead of the code you have above, write something like:
      my $name = param('name'); my $sth = $dbh->prepare("SELECT foo, bar FROM $pictures_table WHERE st +ats = ? AND poster_name = ?"); $dbh->execute(2, $name);
      The above is not only much more robust and secure, it also removes the need to worry about quoting stuff - as this is automagically taken care of by the DBI.

    Cheers,
    Darren :)

      Some DBD modules (and I'm frantically hand-waving here as I can't remember where I've seen it) are very picky about which sections of the SQL statement can include placeholders. Many of them only allow it in the WHERE clause, so using in the FROM clause like that is likely not to work on some databases.

      --
      <http://dave.org.uk>

      "The first rule of Perl club is you do not talk about Perl club."
      -- Chip Salzenberg

      I agree with davorg in that I'd strongly recommend against using a placeholder in the FROM clause. The reason? The replacement string gets quoted, so you'll end up with "select col1, col2 from 'schema.table' ...". I don't know about all databases, but that syntax doesn't work in MySQL or Oracle.

      ---
      It's all fine and dandy until someone has to look at the code.
      In my experience the issue with placeholders is not so much which clause you put them in. For example, many databases allow you to put subqueries in the from clause, assign aliases to them, and treat them as views. Within such subqueries a placeholder would be perfectly legal. The issue is that you can't use a placeholder to substitute for a table name, column name, function name etc. Placeholders can only substitute for values such as numbers and strings.