Stephayne
Stephayne

Reputation: 53

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

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.

Upvotes: 5

Views: 8228

Answers (5)

hobbs
hobbs

Reputation: 239980

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.

Upvotes: 10

Dave Sherohman
Dave Sherohman

Reputation: 46187

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);

Upvotes: 8

Grrrr
Grrrr

Reputation: 2536

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.

Upvotes: 1

Sam Broad
Sam Broad

Reputation: 1

You need to turn the array into a string of values seperated by commas. Try this :

my $zipcodes = join('\',\'',@zips);
SELECT `club_name`,`city` FROM `table` WHERE `public_gig` = 'y' AND `zip` IN ('".$zipcodes."');

Upvotes: -6

TheEye
TheEye

Reputation: 9346

I don't know perl too much, but this looks like a simple SQL problem: why don't you just build the SQL IN clause from your array? You should get something like

AND zip IN ('zip 1', 'zip 2', '...')

I doubt just adding an array in perl will create the right strings for the SQL string ...

Upvotes: -1

Related Questions