Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

Prepared query not accepting || instruction at execution

by jpfarmer (Pilgrim)
on Dec 28, 2002 at 15:13 UTC ( [id://222734]=perlquestion: print w/replies, xml ) Need Help??

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

I am trying to run a select query against a mySQL database using the following code:
my $filter = "('Y' || 'N')"; my $sth = $dbh->prepare(q{SELECT name FROM catagories WHERE catagories +.workrelated = ? ORDER BY name}); $sth->execute($filter);
However, this returns no data. Even if I omit the variable and do this:
my $sth = $dbh->prepare(q{SELECT name FROM catagories WHERE catagories +.workrelated = ? ORDER BY name}); $sth->execute("('Y' || 'N')");
I still get nothing. If I put the information in $filter directly into the prepare statement like this:
my $sth = $dbh->prepare(q{SELECT name FROM catagories WHERE catagories +.workrelated = ('Y' || 'N') ORDER BY name}); $sth->execute();
Then the output is correct. What am I doing that confuses the DBI?

Replies are listed 'Best First'.
Re: Prepared query not accepting || instruction at execution
by dakkar (Hermit) on Dec 28, 2002 at 16:01 UTC

    Placeholders in prepared statements can only be replaced with values, not just any string.

    The fact is, the database driver parses (should parse) the query at prepare time, leaving markers for the missing values. When you substitute something, it is interpreted as a value. So, in your example, you were executing this: SELECT name FROM categories WHERE categories.workrelated = "('Y' || 'N')"; which I'm not surprised to notice didn't return any row.

    The whole perparing business is intended to:

    • ease quoting
    • avoid parsing multiple similar queries
    In your case, the first reason doesn't apply, and I don't think there is a way to accomplish the second.

    -- 
            dakkar - Mobilis in mobile
    
Re: Prepared query not accepting || instruction at execution
by bart (Canon) on Dec 28, 2002 at 16:58 UTC
    Try an SQL statement looking like: SELECT name FROM catagories WHERE workrelated IN('Y','N') ORDER BY name I don't think you can use a placeholder for this kind of filter. You'll have to use oldfashioned string interpolation. Be careful about quoting, if the strings aren't always this simple.
Re: Prepared query not accepting || instruction at execution
by seattlejohn (Deacon) on Dec 28, 2002 at 20:11 UTC
    Part of the problem isn't the DBI, it's that the SQL query you're trying to construct really isn't valid -- or at least won't give you the results you expected. In your final example:
    SELECT name FROM catagories WHERE catagories.workrelated = ('Y' || 'N') ORDER BY name

    MySQL is going to perform a logical-OR on 'Y' and 'N' and come up with a 0. So your query is logically equivalent to this:
    SELECT name FROM catagories WHERE catagories.workrelated = 0 ORDER BY name

    Remember that logical OR is going to take two arguments that are either true or false (or nonzero-but-numeric and zero in MySQL's case) and return a true or false (1 or 0) result. You could rewrite the query like this:
    SELECT name FROM catagories WHERE catagories.workrelated = 'Y' || catagories.workrelated='N' ORDER BY name

    Or better yet do as bart describes and use IN('Y','N') instead.

    By the way, for the sake of programmers who may follow you, I would suggest spelling your table name categories.

            $perlmonks{seattlejohn} = 'John Clyman';

Re: Prepared query not accepting || instruction at execution
by pfaut (Priest) on Dec 28, 2002 at 16:00 UTC

    Using placeholders, mysql is going to compare the field to the text provided for the placeholder. In your case, "('Y' || 'N')". Have you any rows in that table with that text in the workrelated field?

    --- print map { my ($m)=1<<hex($_)&11?' ':''; $m.=substr('AHJPacehklnorstu',hex($_),1) } split //,'2fde0abe76c36c914586c';
      No, just 'Y' or 'N'. I'm trying to select fields that match either 'Y' or 'N'.

        In that case you will need two placeholders: one for the 'Y' and one for the 'N'.

        Using placehodlers will do all the quoting internally for you. This means that your filterstring will be quoted in such a way that it is no longer a boolean operation but a single string to be matched against. Hence, the empty recordset as a result.

        If for reasons internally to the logic of your program, you need the filterstring to be modifiable (e.g. sometimes 'OR' or 'AND' or more or less arguments, ...) then the only solution is to put the SQL string together yourself and not rely on placeholders.

        CountZero

        "If you have four groups working on a compiler, you'll get a 4-pass compiler." - Conway's Law

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://222734]
Approved by Courage
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others learning in the Monastery: (5)
As of 2024-04-19 13:55 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found