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

I have code running a SQL query (select rec_data from foo where id=?), and I do something with the return value. I now have an array of IDs @queryIDs;, how can I run the same query and gather the results in order for the values in this array? Thanks

Replies are listed 'Best First'.
Re: Perl - DBI - How to process array rather than single value?
by ww (Archbishop) on Apr 10, 2014 at 11:24 UTC
    Let the db do it: cf  order by .... in the documentation for your flavor of SQL.

    Downvoted: no code, no code_tags, no effort and off-topic.


    Questions containing the words "doesn't work" (or their moral equivalent) will usually get a downvote from me unless accompanied by:
    1. code
    2. verbatim error and/or warning messages
    3. a coherent explanation of what "doesn't work actually means.

    check Ln42!

      If you read the question they state that existing code they have runs a query for one value, and ask how to execute this for an array of values, how is that "off topic"? They also don't mention the phrase "doesn't work", so I'm not sure why you've added that section. I notice you have not moderated the post suggesting that code tags be added.

      Update: replace . with ?

        They also don't mention the phrase "doesn't work", so I'm not sure why you've added that section

        marto, that is wws new signature, class="pmsig-352046"

Re: Perl - DBI - How to process array rather than single value?
by locked_user sundialsvc4 (Abbot) on Apr 10, 2014 at 12:29 UTC

    Three short answers:

    1. If you need the results of an SQL query to appear in a particular sequence, let the SQL engine do it via ORDER BY.
    2. If you do get an arrayref as the result, use foreach to iterate through it.
    3. However, the arrayref approach would be problematic for a large number of records since all of them would be stored in your program’s memory first.   You can avoid this issue by retrieving the rows one row at a time, say into a hashref where the hash-keys are the column names, using an ordinary while loop.

    There are, of course, copious examples of this on the Internet, both here and elsewhere and to a certain extent within the documentation and manuals for DBI.   (Click on the product-name at the top of that page, right next to the package-author’s name, to see the full list of help-topics associated with the package.   Do a search on the package-name to find even more goodies.)   Usually, you can quickly solve questions like these by surfing for an existing code-example ... a very powerful strategy otherwise not-so diplomatically known as:   “RTFM.”   ;-)

      Considering the query uses '?', i assume it is a placeholder. It seems that he is executing the query with a single value a number of times, and after each run he does something with the returned values.

      Afterward, he has an array of IDs @queryIDs. He wants to execute the the same query (and gather the results in order) for the values in the array.

      This is actually a SQL question, and the answer is, it depends. The quick and dirty (and insecure) method is to join the array with commas and build a dynamic SQL statement with IN().

      To do the same securely, would require splitting the list in SQL, which depends on the RDBMS and version. For example, Oracle 11r2 has a good tokenization method via XMLDB which can be found with a simple search.

Re: Perl - DBI - How to process array rather than single value?
by choroba (Cardinal) on Apr 10, 2014 at 12:26 UTC
    Crossposted at StackOverflow. It is considered polite to inform about crossposting so hackers not attending both sites do not waste their efforts solving a problem already solved at the other side of the Internets.
    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
Re: Perl - DBI - How to process array rather than single value?
by mje (Curate) on Apr 10, 2014 at 13:56 UTC

    Something like (untested):

    my @query_ids = (5,4,3,2,1); my $sql = q/select rec_data from foo where id in (/ . join(",", @query +_ids) . q/) order by id/; my $results = $dbh->selectall_arrayref($sql);

    You can also use placeholders which most people will say are better (which they are) but it depends on how big @query_ids is. Some database engines have quite low limits on the number of parameters. Anyway, to do it that way:

    my @query_ids = (5,4,3,2,1); my $sql = q/select rec_data from foo where id in (/ . join ",", ("?") +x @query_ids .q/) order by id/; print $sql;' select rec_data from foo where id in (?????) order by id my $results = $dbh->selectall_arrayref($sql, undef, @query_ids);

    Are you also asking to get the rows back in the order they are in @query_ids?

      Dynamic SQL is insecure. Dynamic placeholders can be inefficient as the statement will likely not be reused.

      Instead, split the string in SQL via XMLDB or the like. This is not dynamic (especially when defined in the DB itself) and the plan can be reused by the optimizer.

      --

      Edit: Removed comment on limitation. I misread the code. Added more explanation.

      Whereas the per-record loop approach would be: while ($row = $dbh->selectrow_hashref()) or somesuch . . .