PHP PDO 准备语句——MySQL LIKE 查询
Posted
技术标签:
【中文标题】PHP PDO 准备语句——MySQL LIKE 查询【英文标题】:PHP PDO prepared statement -- MySQL LIKE query 【发布时间】:2010-12-19 16:13:51 【问题描述】:我正在尝试通过 php 的 PDO 类(mysql 驱动程序)进行搜索。我有以下查询与 MySQL 客户端一起使用(更改表名以保护无辜者):
SELECT hs.hs_pk,
hs.hs_text,
hs.hs_did,
hd.hd_did,
hd.hd_text,
hv.hv_text,
hc.hc_text
FROM hs
LEFT JOIN hd
ON hs.hs_did = hd.hd_did
LEFT JOIN hd
ON hd.hd_vid = hv.hv_id
LEFT JOIN hc
ON hd.hd_pclass = hc.hc_id
WHERE hs.hs_text LIKE "%searchTerm%"
LIMIT 25;
无论我使用什么搜索词,这都像一个魅力。但是,当我转向 php 时,我无法让它返回任何东西。我尝试了几种看起来合乎逻辑的不同语法,但我没有尝试过。这是我现有的代码:
$handle = fopen('/foo/bar/test.log', 'w+');
fwrite($handle, "doSearch, with search term: $searchTerm\n");
$sql =
'SELECT hs.hs_pk,
hs.hs_text,
hs.hs_did,
hd.hd_did,
hd.hd_text,
hv.hv_text,
hc.hc_text
FROM hs
LEFT JOIN hd
ON hs.hs_did = hd.hd_did
LEFT JOIN hd
ON hd.hd_vid = hv.hv_id
LEFT JOIN hc
ON hd.hd_pclass = hc.hc_id
WHERE hs.hs_text LIKE :searchTerm
LIMIT 25';
try
$dbh = new PDO('mysql:host=localhost;dbname=awdb', "user", "password");
fwrite($handle, "connected to DB\n");
$prep = $dbh->prepare($sql);
$ret = $prep->execute(array(':searchTerm' => '"%'.$searchTerm.'%"'));
while ($row = $prep->fetch(PDO::FETCH_ASSOC))
$i++;
$result[$i]['subText'] = $row['hs_pk'];
$result[$i]['subText'] = $row['hs_text'];
$result[$i]['subDid'] = $row['hs_did'];
$result[$i]['devDid'] = $row['hd_did'];
$result[$i]['devText'] = $row['hd_text'];
$result[$i]['vendorText'] = $row['hv_text'];
$result[$i]['classText'] = $row['hc_text'];
$dbh = null;
catch (PDOException $e)
print "Error!: " . $e->getMessage() . "<br/>";
die();
我也尝试了以下方法(SQL WHERE 子句和 prep->执行行都发生了变化):
WHERE hs.hs_text LIKE CONCAT(\'%\', ?, \'%\')
$ret = $prep->execute(array($searchTerm));
WHERE hs.hs_text LIKE "%:searchTerm%"
$ret = $prep->execute(array(':searchTerm' => $searchTerm));
WHERE hs.hs_text LIKE ":searchTerm"
$ret = $prep->execute(array(':searchTerm' => '%'.$searchTerm.'%'));
等等……
【问题讨论】:
这可能只是一个转置问题,但你没有附上你的 sql 语句 - 你需要在它的末尾加上一个撇号 (')。 这是一个换位问题。如果我忘记了 ' 我相信 PHP 会完全吓坏的,哈哈。不过,感谢您非常快速的回复。 var_dump() $dbh、$prep 和 $ret 会得到什么?它们是您期望的值吗?您是否尝试过使用 mysql_* 系列函数运行相同的查询进行比较? 这里是每个(以及脚本的输出)的 var 转储:doSearch,搜索词:com connected to DB object(PDO)#32 (0) object(PDOStatement) #33 (1) ["queryString"]=> string(586) "SELECT ...语句太大,但与脚本中的 $sql 变量匹配... bool(false) ret: Array ( ) 结果:应该添加行我没有尝试过 mysql_* 系列函数。我需要查找文档,因为我不熟悉这些。 【参考方案1】:$ret = $prep->execute(array(':searchTerm' => '"%'.$searchTerm.'%"'));
这是错误的。你不需要双引号。
WHERE hs.hs_text LIKE ":searchTerm"
$ret = $prep->execute(array(':searchTerm' => '%'.$searchTerm.'%'));
这也是错误的。 尝试:
$prep = $dbh->prepare($sql);
$ret = $prep->execute(array(':searchTerm' => '%'.$searchTerm.'%'));
说明:准备好的语句不只是简单地进行字符串替换。它们传输数据与查询完全分开。只有在将值嵌入查询时才需要引号。
【讨论】:
感谢您的解释。可能解决不了这个问题,但我会记在内存中以备日后使用。 @Tlm 你还是应该接受他的回答。它直接回答了您的问题。接受它不需要任何费用。【参考方案2】:$prep = $dbh->prepare($sql);
$ret = $prep->execute(array('searchTerm' => $searchTerm));
【讨论】:
这个分析器不完整(你指的是哪个 $sql?),缺少一些信息(如何进行“.. LIKE '%FOO%'”搜索?)并且缺少任何信息解释。像这样放置的一些代码不是答案,IMO,只是一个断章取义的事情。【参考方案3】:好吧,我解决了这个问题。坦率地说,我是个白痴……感谢大家看到这一点并提供良好的反馈。问题是表名中的拼写错误(我更改了,所以这里没有人能够看到我的问题开始......)。不过,这些建议确实让我找到了问题所在,所以谢谢亚当、jkndrkn 和 troelskn。
作为记录,以下组合效果很好:
WHERE aw_hcl_subdevices.hs_text LIKE CONCAT(\'%\', ?, \'%\')
$ret = $prep->execute(array($searchTerm));
【讨论】:
-1 这不是正确的方法。您应该不将 CONCAT() 用于三个 static 字符串文字,因为它会为您打开特定类型的 SQL 注入(我忘记了名称)。 不知道是谁对上述评论投了赞成票,但奇怪的是——他们都没有说出注射的名字。可能是因为这种“注入”根本不存在。 如果@TheodoreR.Smith 还在 SO 附近,他很想听听他的意见。 More specifically on this distinct question 如果你用谷歌搜索“静态字符串 sql 注入”,这是第一个结果。 @Mike,你的意思是这样的问题,由上面的评论产生? This?这看起来像The Bible said that all words in The Bible are true.
以上是关于PHP PDO 准备语句——MySQL LIKE 查询的主要内容,如果未能解决你的问题,请参考以下文章
使用 PHP PDO 准备语句和 MySQL 选择字段为空的行