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

I'm trying to pull some data from a SQLite DB, where I need to execute very similar queries several times. Specifically, I want to pull the list of distinct values out of 3 different columns. I then want to be able to push the list of distinct values into their own arrays, so I can molest them later.

The brute force way to do it is:

# query to get Centers $cent_sth=$dbh->prepare("SELECT DISTINCT Center FROM People"); $cent_sth->execute() or die "Failed to retrieve list of centers from d +atabase. $DBI::errstr"; print " Centers are:\n"; while (@centers = $cent_sth->fetchrow_array()) { print "\t@centers[0]\n" unless (@centers[0]!~/^\d{2} -/); } # query to get Divsions $div_sth=$dbh->prepare("SELECT DISTINCT Div FROM People"); $div_sth->execute() or die "Failed to retrieve list of centers from da +tabase. $DBI::errstr"; print " Divisions are:\n"; while (@divs = $div_sth->fetchrow_array()) { print "\t@divs[0]\n"; } # query to get Departments $dept_sth=$dbh->prepare("SELECT DISTINCT Dept FROM People"); $dept_sth->execute() or die "Failed to retrieve list of centers from d +atabase. $DBI::errstr"; print " Departments are:\n"; while (@depts = $dept_sth->fetchrow_array()) { print "\t@depts[0]\n"; }

I think I ought to be able to do the same thing by looping over the same code 3 times. Something like:

my %orgs = ("Center", "cent_sth", "Div", "div_sth", "Dept", "dept_sth" +) while (($name, $this_sth)=each (%orgs)){ $this_sth=$dbh->prepare("SELECT DISTINCT $name FROM People"); $this_sth->execute() or die "Failed to retrieve list of $name from + database. $DBI::errstr"; }

But I'm pretty sure I'm not naming my statement handlers in a way that will allow me to use them later. What's the smart way to do this?

Replies are listed 'Best First'.
Re: Looping over multiple queries
by JavaFan (Canon) on Jan 28, 2010 at 15:23 UTC
    One way of doing that is:
    my @names = qw[Center Div Dept]; my %orgs; foreach my $name (@names) { $orgs{$name} = $dbh->prepare("SELECT DISTINCT $name FROM People") +or die; $orgs{$name}->execute or die; }
    And if you want to access a single element of an array, better write that as $depts[0] instead of @depts[0].

      OK, JavaFan, I think you're suggestion works and I *think* I understand it (mostly). Now, my problem is I'm still to much of a noob at handling hash references to know the syntax for extracting the data out of %orgs.

      I could keep plowing through Man Perl and surfing Google ... or you could tell me ;^)

      Thanks again for the tip

        Oops. I spoke too soon. I think I got it:

        while (($k, $v)=each (%orgs)){ while (@k = $v->fetchrow_array()) { print "\t$k[0]\n"; } }

        Unless there's a simpler way?
        Thanks again for the tip :^)

        Now, my problem is I'm still to much of a noob at handling hash references
        That's not a problem.

        However, what is a problem is that you fail to realize my code snippet doesn't use a hash reference at all. There's a hash - not a reference to a hash.

        Perhaps you want to read an introduction book about Perl first?

        Read through perlintro before you try doing anything else , really :)
Re: Looping over multiple queries
by ww (Archbishop) on Jan 29, 2010 at 00:11 UTC
    "execute very similar queries several times"

    See "placeholders" in perldoc DBI" or use Super Search or even peruse the SQLite documentation and -- if this is not a long-running job -- feed the vars, as needed, from a lookup table or from the CLI.

    "brute force way"

    ...may be less than optimum (in terms of speed, if that's an issue); see this re Transactions -- which may be relevant (or not)/

      Placeholders don't work in this context: They can only be used to specify values, not fields. (Change the values, and you have the same SQL statement with a minor parameter change. Change the fields, and you have a very different SQL statement, as far as most databases are concerned.)