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

How do I create a PDO parameterized query with a LIKE statement?

提问人:Andrew G. Johnson 提问时间:2/25/2009 最后编辑:George GAndrew G. Johnson 更新时间:1/17/2022 访问量:117547

问:

这是我的尝试:

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

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

while ($results = $query->fetch()) 
{
    echo $results['column'];
}
PHP 的PDO协议

评论


答:

142赞 Andrew G. Johnson 2/25/2009 #1

我发帖后马上就想通了:

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

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

评论

1赞 logan 4/4/2014
@Andrew:如果使用多个怎么办?执行数组应该如何按顺序执行?like
0赞 sdjuan 11/9/2016
谢谢。csharp + Mysql + ODBC 有类似的问题,使用 like 它不会使用“select * from table where column like '%?%';” 但如果我像您一样“select * from table where column like ?;” 并设置参数字符串,以便: string frag = $“%{searchFragment}%”;然后使用 frag 作为参数值。奇怪
2赞 Peter Bagnall 11/13/2016
PDO 应该在执行调用中转义该 %。Kaqai的答案更好
0赞 Dan Robinson 3/8/2018
值得注意的是,PDOStatement::bindParam 文档页面上的顶级用户贡献注释提供了一种不同的方法:在绑定变量之前将百分号添加到变量中。
0赞 RationalRabbit 12/14/2019
看看 gavin 的解决方案,摘自 Your Common Sense 的页面,靠近此线程底部。简单。逻辑。
109赞 Kzqai 9/9/2011 #2

对于使用命名参数的用户,以下是对 MySQL 数据库进行部分匹配的方法:LIKE%

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

其中命名参数为 。:dangerousstring

换言之,在你自己的查询中使用显式未转义的符号,这些符号是分开的,绝对不是用户输入。%

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

WHERE column_name LIKE '%' || :dangerousstring || '%'

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

当您想在 搜索字符串,而不让它充当通配符。%_

因此,在组合喜欢和参数化时,这是需要注意的另一件事。

评论

6赞 Aaron Newton 4/21/2015
+1 - 这对我来说似乎是一个很好的方法,因为所有串联都发生在占位符被替换后在数据库中,这意味着可以使用命名占位符。值得一提的是,上面的语法是针对 Oracle 的——在 MySQL 中,语法是 .参考: stackoverflow.com/a/661207/201648LIKE CONCAT('%', :something, '%')
1赞 Christopher Smit 6/17/2017
这并不完全适合我,但让我走上了正确的轨道。我必须像'%':'%'一样做一些事情才能工作。
2赞 Thiago Dias 1/10/2018
我知道这是题外话,但我甚至能够使用这个语句来执行 SQL 注入,为什么?
0赞 Luzan Baral 10/26/2018
这对我不起作用,我还用 SQL 命令对其进行了测试,这会给我带来错误。SELECT * FROM calculation WHERE ( email LIKE '%' || luza || '%' OR siteLocation LIKE '%'|| luza ||'%' OR company LIKE '%' ||luza ||'%' )
1赞 Your Common Sense 2/2/2020
@AaronNewton .当你在PHP中连接时,命名占位符怎么会成为问题?显然,在 PHP 中连接同时支持命名和位置,并且更具可移植性,因为您可以对任何数据库使用相同的查询。我真的不明白为什么这么多人认为命名占位符和位置占位符之间有任何区别。and it means named placeholders can be used
20赞 Blazer 9/15/2012 #3
$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赞 felwithe 5/15/2015
与公认的答案相比,使用它有什么优势吗?使用可以防止注入攻击吗?公认的答案基本上否定了使用占位符的价值,方法是将搜索字符串连接起来,以达到过去的样子。bindValue?%
0赞 ssi-anik 7/4/2015
在 $query->rowCount() == 0 之前使用否定有什么意义?这真的有意义吗?
17赞 Vijaysinh Parmar 8/5/2015 #4

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

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

评论

0赞 josliber 9/27/2015
我编辑了你的帖子,将代码放入代码块中 - 你可以在 stackoverflow.com/help/formatting 阅读有关帖子格式的更多信息。其他一些用户选择对你的答案投反对票而不发表评论,所以我不确定投反对票的原因。
0赞 Ozkar R 9/27/2015 #5

PDO 转义“%”(可能导致 sql 注入):在查找匹配部分字符串时,使用前面的代码将给出所需的结果,但如果访问者键入字符“%”,即使您没有在数据库中存储任何内容,您仍然会得到结果(这可能会导致 sql 注入)

我尝试了很多变化,所有变化都具有相同的结果:PDO 正在转义“%”导致不需要/不兴奋的搜索结果。

我虽然值得分享,但如果有人在它周围找到了一个词,请分享它

评论

1赞 Ozkar R 9/27/2015
这是来自手册:us3.php.net/manual/en/pdo.prepared-statements.php 这是另一篇关于主题的帖子:stackoverflow.com/questions/22030451/......我真的很想知道你对这个issu的看法。
1赞 Ozkar R 9/27/2015
可能的解决方案(未测试) 使用 CONCAT,例如:$sql = “SELECT item_title FROM item WHERE item_title LIKE CONCAT('%',?,'%')”;参考: blog.mclaughlinsoftware.com/2010/02/21/php-binding-a-wildcard
3赞 Your Common Sense 9/27/2015
PDO 不会转义 %。是你的代码做错了。对于解决方案,您应该阅读此处已经提供的答案
0赞 Ozkar R 9/27/2015
谢谢你的建议。无论如何,测试的代码是手册中的代码,使用占位符来避免SQL注入,我仍然得到相同的结果 Example #6 使用上述代码而不是我的代码,对占位符 PDO 的无效使用确实转义了 %。我是论坛的新手,我可能不明白评论、发帖和声誉的过程在这里是如何运作的,我会在下一次牢记这一点,因为根据之前的评论,你需要声誉来帮助他人或发表评论。谢谢。
5赞 kjdion84 1/30/2017 #6

这工作原理:

search `table` where `column` like concat('%', :column, '%')
3赞 gavin stanley 7/15/2019 #7

我从php妄想中得到这个

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

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

0赞 zdarma 2/3/2021 #8

我有类似的需求,但使用的是从表单中获取的变量。我这样做是为了使用 PHP 从我的 PostgreSQL 数据库中获取结果:

<?php
     $player = $_POST['search'];  //variable from my search form
     $find = $sqlPDO->prepare("SELECT player FROM salaries WHERE player ILIKE ?;");
     $find->execute(['%'.$player.'%']);

     while ($row = $find->fetch()) {
         echo $row['player']."</br>";
     }
?>

“ILIKE”使搜索不区分大小写,因此搜索 cart 或 Cart 或 cARt 都将返回相同的结果。

评论

3赞 Your Common Sense 2/3/2021
从字面上看,它与接受的答案中的代码相同。
0赞 zdarma 2/3/2021
实际上,不,不是,有区别。如果您认为它们实际上是相同的答案,您可能需要检查一下眼睛。
0赞 F. Müller 2/3/2021
@zdarma我认为他的意思是代码几乎相同,它并没有真正添加那么多新的关键信息。如果有人看到公认的答案,他可以在一秒钟后想出这个答案。这太明显了。StackOverflow 的想法是,您可以提供易于理解的独特答案并添加一些有价值的东西。您可以参考其他答案并给予他们信任,然后添加您自己的想法(鉴于 X 的解决方案,我想更改/添加 x、y、z 原因)。一旦你有50+代表,你就可以在帖子下写评论,批评或添加你的想法。
1赞 Nico Haase 2/3/2021
请强调与其他答案的差异,以便其他人可以从中学习
-2赞 MrT2022 1/17/2022 #9

我能做到这一点的唯一方法是将 %$search% 放入另一个变量中。

    if(isset($_POST['submit-search'])){
         $search = $_POST['search'];
   }
    
        $query = 'SELECT * FROM posts WHERE post_title LIKE :search';
        $value ="%$search%";
        $stmt= $pdo->prepare($query);
        
        $stmt->execute(array(':search' => $value));

我不知道这是否是最好的方法,在我使用的 while 循环中:

while ($r = $stmt->fetch(PDO::FETCH_ASSOC)){