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

I have 3 sql queries each is almost same except that the condition varies each time and on different column eg.

$sql="Select * where coln1='?'"; $sql1="Select * where coln2='?'"; $sql2="Select * where coln3='?'";

how to convert them into prepare and execute method of writing a query a perl

Replies are listed 'Best First'.
Re: PERL DBI MODULE
by Corion (Patriarch) on May 19, 2014 at 11:26 UTC

    I would keep them as three separate SQL statements.

    Alternatively, DBIx::PreQL allows you to construct different SQL statements from the same SQL template.

    If you really want to convert them into one SQL statement, you can convert the three statements into one statement as below. Likely, the query planner will not generate a good plan for this:

    my $sql= <<'SQL'; select * from mytable -- ignore or value where (? or coln1=?) and (? or coln2=?) and (? or coln3=?) SQL my $sth= $dbh->prepare( $sql ); my %parameters= (coln2 => 'Hello'); my @parameters; for my $column (qw(coln1 coln2 coln3) { if( exists $parameters{ $column }) { # Use this column value push @parameters, 0, $parameters{ $column }; } else { # Ignore this column value push @parameters, 1, undef; }; }; $sth->execute(@parameters);
Re: PERL DBI MODULE
by marto (Cardinal) on May 19, 2014 at 11:30 UTC

    I don't think I understand what you're asking. If you are suggesting that you want to make the column (or table, since isn't one in your example SQL) name a placeholder DBI says:

    "With most drivers, placeholders can't be used for any element of a statement that would prevent the database server from validating the statement and creating a query execution plan for it. For example"

    "SELECT name, age FROM ?" # wrong (will probably fail) "SELECT name, ? FROM people" # wrong (but may not 'fail')
Re: PERL DBI MODULE
by Tux (Canon) on May 19, 2014 at 13:44 UTC

    As said by others, your quest is kinda dubious.

    My first warning/quest after reading the OP is: "Do you really mean to match coln1 against a literal '?'?

    If you want to match against a parameter in the execute that will not DWIM at all.

    my %sth = map { $_ => $dbh->prepare ("select * from foo where $_ = ?") + } qw( coln1 coln2 coln3 ); # Note the unquoted ? $sth{coln1}->execute ($coln1_val); # query for coln1 executed with ? r +eplaced with $coln2_val

    Enjoy, Have FUN! H.Merijn
Re: PERL DBI MODULE
by chacham (Prior) on May 19, 2014 at 12:23 UTC

    They are three different queries because the COLUMN is different. They would each be prepared and executed separately.

    If you are looking for how to prepare and execute a SQL query in general, you can check the dbi set of module best fit for your RDBMS.

      You're right.

      Of course one could union several queries together, like so (assuming the same table t):

      ( select * from t where coln1='?' ) union all ( select * from t where coln2='?' ) union all ( select * from t where coln3='?' ) -- ... (etcetera)

      This way there is only one database/network trip. Of course, it can easily make the call side (application) more complicated and I wouldn't recommend it. But it's not so long ago that that performance gain could be irresistable.

        Of course, it can easily make the call side (application) more complicated

        Yep. To know which clause returned which data might require more work. Without the context, it's hard to tell.

        As for network usage, on queries that return more data, the sending is insignificant. But i think you already said that. :)

Re: PERL DBI MODULE
by locked_user sundialsvc4 (Abbot) on May 19, 2014 at 12:47 UTC

    Strongly agree.   You will need to run separate queries, and if the actual number of queries to be run is not unreasonably large, I would definitely prefer to read code that just repeats itself just repeats itself just repeats itself.   Because, that way, when, not if one of the cases has to be changed, you can easily do so because they are not “tightly coupled” to one another ... you just change the one.   And, each one of them is very clear, very easy to understand.

    If you do find that you need to change only the field-name, and the set of field-names is known trustworthy, then you can easily do that by ordinary string interpolation, e.g.:

    for my $field_name (qw/field1 field2 field3/) { my $sql = "select * from table1 where $field_name = '?'"; ...
    Since double-quotes are used, the value of $field_name will be interpolated into the string. ... and in this case what you are emphasizing to the Gentle Programmer who will follow in your footsteps is that the queries are exactly the same except for this name.   Notice that in the resulting query-strings I am still using a placeholder ... '?' ... and I will still provide the field’s value to each query in that manner.   I will execute each query in turn and in some useful manner accumulate the results.