Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MySQL - Perl: How to use an array with IN within a select query? (WHERE IN (@array))

Tags:

arrays

mysql

perl

This is an addition to my solved question here: how to get array of zip codes within x miles in perl

OK, I have the array @zips. Now I am trying to use it in a query like this:

SELECT `club_name`,`city` FROM `table` WHERE `public_gig` = 'y' AND `zip` IN (@zips)
#I also tried syntax "IN ("@zips"), IN @zips and IN ('@zips')"

But, I cannot get it to work. (I am using placeholders and such as you see in my link above.)

I was able to get this to work:

$fzip=shift(@Zips);
$lzip=pop(@Zips);
SELECT `club_name`,`city` FROM `table` WHERE `public_gig` = 'y' AND `zip` BETWEEN $fzip AND $lzip

    ZIP | public_gig | start_time | fin_time | city       | club_name | and so on
  33416 | y          | 9pm        | 2am      | clearwater | beach bar | yada

But, for obvious reasons and some resemblance of accuracy, that is not really what I want. Just wanted to see if I could get SOMETHING working on my own.

Why can't I get the query to work with the zips in the array using IN?? Nothing is returned and there is no error.

There is actually a lot more in that query but, I left it all out to keep it short here.

I tried to figure it out by myself. Obviously, my learning capacity for the day is near peak.

Thanks for any help.

like image 763
Stephayne Avatar asked Feb 28 '11 22:02

Stephayne


People also ask

Can we use Array in where clause?

We can pass an array with the help of where IN clause. Let us first create a new table for our example. Let us now insert records. To display all records.


3 Answers

All of the examples posted here will screw up if any of your values contain single-quotes, don't use them.

Instead (assuming $dbh is the database handle for your mysql connection):

my $zip_string = join q{,}, map $dbh->quote($_), @zips;

and interpolate that.

Or, for something nice, but not half as outlandish as DBIx::Perlish: SQL::Abstract.

my $sqla = SQL::Abstract->new;
my ($sql, @bind) = $sqla->select(
  'table', 
  ['club_name', 'city'],
  {
    public_gig => y',
    zip => { -in => \@zips },
  }
);

$dbh->prepare($sql);
$dbh->execute(@bind);
# fetchrow etc.
like image 51
hobbs Avatar answered Oct 13 '22 20:10

hobbs


This can be done using placeholders, you just have to work around the limitation that each placeholder can only accept a single value. WHERE zip IN (?) won't work because you're (presumably) looking for more than one value (otherwise, why use IN?).

You can, however, easily build a statement on the fly with the correct number of placeholders:

#!/usr/bin/env perl

use strict;
use warnings;

my @zips = (12345, 54321, 90210);
my $stmt = "SELECT `club_name`,`city`
            FROM `table`
            WHERE `public_gig` = 'y' AND `zip` IN ("
           . join(', ', ('?') x @zips) . ')';

print "$stmt\n";

# Now just:
# my $sth = $dbh->prepare($stmt);
# $sth->execute(@zips);
like image 33
Dave Sherohman Avatar answered Oct 13 '22 22:10

Dave Sherohman


Alternatively, if you don't mind using weird CPAN modules, with DBIx::Perlish you can just say:

my @results = db_fetch {
   my $t: table;
   $t->public_gig eq "y";
   $t->zip  <-  @zips;
};

and it will do the right thing.

Full disclosure: I am the author of DBIx::Perlish.

like image 1
Grrrr Avatar answered Oct 13 '22 21:10

Grrrr