我有一个查询来计算基于文档的某个半径范围内的对象: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";
然后我做
my $points = $y->dbh->prepare($sql);
$results = $points->execute($lat, $lng, $rad, $units, '(type1, type2)');
其中&#39;(type1,type2)&#39;应该传递给
b.type IN ?
(靠近SQL的底部)。
我已经尝试过各种各样的方式,我可以想到逃避这个字符串以便它起作用(包括很多方式,显然是疯了但我已经绝望了)inc
'(type1, type2)'
'\(\'type1\', \'type2\'\)'
'(\'type1\', \'type2\')'
"('type1', 'type2')"
等(我已经尝试了很多我无法记住的东西。)
无论我尝试什么,我都会遇到
形式的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'
根据我试图逃避字符串的方式,错误消息略有不同,但始终与sql的相同部分有关。
我现在认为逃避不是我的问题而且我错过了一些关于执行的事情。如果我在DB中运行代码,它可以正常使用IN语句,即b.type IN(&#39; type1&#39;,&#39; type2&#39;)工作正常。
有人可以开导我吗?我该怎么做?
由于
答案 0 :(得分: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);