如何使用LIKE语句创建PDO参数化查询?


107

这是我的尝试:

$query = $database->prepare('SELECT * FROM table WHERE column LIKE "?%"');

$query->execute(array('value'));

while ($results = $query->fetch()) 
{
    echo $results['column'];
}

Answers:


124

我发布后马上想通了:

$query = $database->prepare('SELECT * FROM table WHERE column LIKE ?');
$query->execute(array('value%'));

while ($results = $query->fetch())
{
    echo $results['column'];
}

1
@Andrew:如果使用倍数like怎么办?execute数组应如何按顺序执行?
logan 2014年

谢谢。对于csharp + Mysql + ODBC使用类似的问题,因为它不会使用“ select * from table where column like'%?%';”返回任何行;但是,如果我愿意的话,您会选择“从表中的*列中选择*吗?”。并将参数字符串设置为:string frag = $“%{searchFragment}%”; 然后使用frag作为参数值。很奇怪
sdjuan '16

2
PDO应该在执行调用中转义该%。Kaqai的答案更好
Peter Bagnall

似乎值得注意的是,PDOStatement :: bindParam文档页面上由用户提供的最高注释提供了另一种方法:在绑定变量之前将百分号添加到变量。
丹·罗宾逊

看一下加文(Gavin)的解决方案,该解决方案取自您常识页面的该线程底部附近。简单。逻辑上。
RationalRabbit

85

对于使用命名参数的用户,以下是如何LIKEMySQL数据库的%部分匹配一起使用:

WHERE column_name LIKE CONCAT('%',:dangerousstring,'%')

其中命名参数为:dangerousstring

换句话说,%在您自己的查询中使用显式未转义的符号,这些符号是分开的,并且绝对不是用户输入。

编辑:Oracle数据库的串联语法使用串联运算符:||,因此它将简单地变为:

WHERE column_name喜欢'%'|| :dangerousstring || '%'

但是,有一些警告,如@bobince 在这里提到的那样:

困难 来的时候,你要允许文字%_搜索字符串中的字符,而不用它作为通配符。

因此,在将like和parameterization结合使用时,还需要注意其他事项。


6
+1-对我来说这似乎是一个好方法,因为所有串联都发生在替换占位符之后的数据库中,这意味着可以使用命名的占位符。值得一提的是,以上语法是针对Oracle的-在MySQL中,语法为LIKE CONCAT('%', :something, '%')。参考:stackoverflow.com/a/661207/201648
亚伦·牛顿

1
这并不完全适合我,但可以让我走上正确的道路。我必须做'%'这样的东西:'%'才能正常工作。
Christopher Smit

我知道这是题外话,但是即使使用此语句我也可以执行sql注入,为什么?
Thiago Dias

这对我不起作用,我还用SQL命令对其进行了测试,SELECT * FROM calculation WHERE ( email LIKE '%' || luza || '%' OR siteLocation LIKE '%'|| luza ||'%' OR company LIKE '%' ||luza ||'%' )这会给我错误。
卢赞·巴拉

@AaronNewton and it means named placeholders can be used。当您在PHP中串联时,命名占位符怎么回事?显然,PHP中的级联支持命名和位置,并且更便于移植,因为您可以对任何数据库使用相同的查询。我真的不明白为什么这么多人认为命名占位符和位置占位符之间有什么区别。
您的常识

18
$query = $database->prepare('SELECT * FROM table WHERE column LIKE ?');
$query->bindValue(1, "%$value%", PDO::PARAM_STR);
$query->execute();

if (!$query->rowCount() == 0) 
{
    while ($results = $query->fetch()) 
    {
        echo $results['column'] . "<br />\n";
    }       
} 
else 
{
    echo 'Nothing found';
}

1
与公认的答案相比,使用它有什么优势吗?使用bindValue可以防止注入攻击吗?公认的答案基本上是?通过将搜索字符串串联起来,否定使用占位符的价值%
felwithe

在$ query-> rowCount()== 0之前使用否定的意义是什么?这真的有意义吗?
ssi-anik

14

您也可以尝试这个。我面临类似的问题,但经过研究取得了结果。

$query = $pdo_connection->prepare('SELECT * FROM table WHERE column LIKE :search');

$stmt= $pdo_connection->prepare($query);

$stmt->execute(array(':search' => '%'.$search_term.'%'));

$result = $stmt->fetchAll(PDO::FETCH_ASSOC);

print_r($result);

我编辑了您的帖子,以将代码放入代码块中-您可以在stackoverflow.com/help/formatting上阅读有关帖子格式的更多信息。其他一些用户选择对您的答案进行不合格投票而不发表评论,因此我不确定造成不合格的原因。
josliber

2
再说一遍,我没有对你的问题投票。别人不赞成。
josliber

3

这有效:

search `table` where `column` like concat('%', :column, '%')

2

我是从php妄想中得到的

$search = "%$search%";
$stmt  = $pdo->prepare("SELECT * FROM table WHERE name LIKE ?");
$stmt->execute([$search]);
$data = $stmt->fetchAll();

它对我有用,非常简单。就像他说的那样,在将其发送到查询之前,您必须“首先准备我们完整的文字”


0

PDO会转义“%”(可能导致sql注入):如果希望访问部分字符串,则使用先前的代码会产生期望的结果,如果访问者键入字符“%”,即使您不输入,也会获得结果t数据库中没有存储任何内容(可能导致sql注入)

我已经尝试了很多变体,所有这些都具有相同的结果,PDO转义了“%”导致不需要的/未激活的搜索结果。

我很值得分享,如果有人发现它周围的单词,请分享


1
这是来自手册:us3.php.net/manual/en/pdo.prepared-statements.php 这是关于主题的另一篇文章:stackoverflow.com/questions/22030451/… 我真的很想知道您对这个问题
Ozkar R 2015年

1
可能的解决方案(未测试)使用CONCAT,如:$ sql =“从项目WHERE的item_title中选择SELECT item_title喜欢CONCAT('%',?,'%')”;参考:blog.mclaughlinsoftware.com/2010/02/21/php-binding-a-wildcard
Ozkar R

3
PDO无法逃脱%。是你的代码做错了。对于该解决方案,您应该阅读这里已经提供的答案
您的常识2015年

感谢您的建议。无论如何,测试的代码是手册中的代码,使用占位符来避免SQL注入,我仍然得到相同的结果。示例#6无效使用占位符 PDO使用上述代码(而不是我的代码)逃逸了%。我是新来的论坛,我可能不明白这里的评论,发布和声誉流程的工作方式,下一个我会牢记在心,因为在上一个评论的基础上,您需要声誉来帮助他人或发表评论。谢谢。
Ozkar R 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.