传递DBI-> IN子句的执行值时出现perl错误

mar*_*ark 2 perl dbi

我有一个查询来计算基于文档的点的某个半径范围内的对象:http://www.plumislandmedia.net/mysql/haversine-mysql-nearest-loc/

它工作得非常好但是我只想搜索那些特定类型的对象,这导致了一个问题;

代码如下所示:

my $sql = "SELECT *
 FROM (
 SELECT b.*, pr.postcode, pr.prize, pr.title, pr.collection, pr.redeemed, pr.delivery, pr.archived, bt.category,
        p.radius,
        p.distance_unit
                 * DEGREES(ACOS(COS(RADIANS(p.latpoint))
                 * COS(RADIANS(b.lat))
                 * COS(RADIANS(p.longpoint - b.lng))
                 + SIN(RADIANS(p.latpoint))
                 * SIN(RADIANS(b.lat)))) AS distance
  FROM bubbles AS b, bubble_prizes AS pr, bubble_types AS bt
  JOIN (   /* these are the query parameters */
        SELECT  ?  AS latpoint, ? AS longpoint,
                ? AS radius,      ? AS distance_unit
    ) AS p
  WHERE b.lat
     BETWEEN p.latpoint  - (p.radius / p.distance_unit)
         AND p.latpoint  + (p.radius / p.distance_unit)
    AND b.lng
     BETWEEN p.longpoint - (p.radius / (p.distance_unit * COS(RADIANS(p.latpoint))))
         AND p.longpoint + (p.radius / (p.distance_unit * COS(RADIANS(p.latpoint))))
    AND pr.bubble = b.id
    AND b.type IN ?
    AND b.type = bt.type
 ) AS d
 WHERE distance <= radius
 ORDER BY distance";    
Run Code Online (Sandbox Code Playgroud)

然后我做

my $points = $y->dbh->prepare($sql);
$results  = $points->execute($lat, $lng, $rad, $units, '(type1, type2)');
Run Code Online (Sandbox Code Playgroud)

其中'(type1,type2)'应传递给

b.type IN ?
Run Code Online (Sandbox Code Playgroud)

(它接近SQL的底部).

我已经尝试了各种方法,我可以想到逃避这个字符串,以便它的工作(包括很多方式,显然是疯了但我变得绝望)inc

'(type1, type2)'
'\(\'type1\', \'type2\'\)'
'(\'type1\', \'type2\')'
"('type1', 'type2')"
Run Code Online (Sandbox Code Playgroud)

等等(我已经尝试了很多我甚至都记不起来的东西.)

无论我尝试什么,我都会得到表单的SQL错误

DBD::mysql::st execute failed: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''(type1, type2)'
    AND b.type = bt.type
 ) AS d
 WHERE distance <= radius'
Run Code Online (Sandbox Code Playgroud)

根据我试图逃避字符串的方式,错误消息略有不同,但始终与sql的相同部分有关.

我现在认为逃避不是我的问题,我错过了一些关于执行的东西.如果我在DB中运行代码,它可以正常使用IN语句iebtype IN('type1','type2')正常工作.

有人可以开导我吗?我该怎么做?

谢谢

AKH*_*and 5

您需要在IN (...)语句中使用占位符.整个问题execute()是避免SQL注入,而你基本上是在尝试在那里注入SQL.你可以制作动态的占位符列表,如下所示:

my @types = qw(type1 type2);
my $placeholders = join ", ", ("?") x @types;
my $sql = "...
        b.typeID IN ($placeholders)
    ...";
my $points = $y->dbh->prepare($sql);
$results  = $points->execute($lat, $lng, $rad, $units, @types);
Run Code Online (Sandbox Code Playgroud)