127

Here's my attempt at it:

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

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

while ($results = $query->fetch()) 
{
    echo $results['column'];
}
George G
  • 7,443
  • 12
  • 45
  • 59
Andrew G. Johnson
  • 26,603
  • 30
  • 91
  • 135

9 Answers9

141

Figured it out right after I posted:

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

while ($results = $query->fetch())
{
    echo $results['column'];
}
George G
  • 7,443
  • 12
  • 45
  • 59
Andrew G. Johnson
  • 26,603
  • 30
  • 91
  • 135
  • 1
    @Andrew: what if multiple `like` is used ? how should the execute array executes in order ? – logan Apr 03 '14 at 18:00
  • thanks. had similar issue with csharp + Mysql + ODBC using like it would not return any rows using "select * from table where column like '%?%';" but will if I do like you did "select * from table where column like ?;" and set the parameter string so: string frag = $"%{searchFragment}%"; then use frag for the parameter value. Weird – sdjuan Nov 08 '16 at 19:34
  • 2
    PDO should be escaping that % in the execute call. Kaqai's answer is better – Peter Bagnall Nov 13 '16 at 14:52
  • It seems worth noting that the top [user-contributed note](http://php.net/manual/en/pdostatement.bindparam.php#99698) on the [PDOStatement::bindParam documentation page](http://php.net/manual/en/pdostatement.bindparam.php) offers a different approach: Add the percent sign(s) to the variable before binding it. – Dan Robinson Mar 07 '18 at 16:31
  • Take a look at gavin's solution, taken from Your Common Sense's page, near the bottom of this thread. Simple. Logical. – RationalRabbit Dec 14 '19 at 15:40
107

For those using named parameters, here's how to use LIKE with % partial matching for MySQL databases:

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

where the named parameter is :dangerousstring.

In other words, use explicitly unescaped % signs in your own query that are separated and definitely not the user input.

Edit: Concatenation syntax for Oracle databases uses the concatenation operator: ||, so it'll simply become:

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

However there are caveats as @bobince mentions here that:

The difficulty comes when you want to allow a literal % or _ character in the search string, without having it act as a wildcard.

So that's something else to watch out for when combining like and parameterization.

Christian
  • 332
  • 1
  • 7
  • 19
Kzqai
  • 22,588
  • 25
  • 105
  • 137
  • 6
    +1 - this seems like a good approach to me since all of the concatenation happens in the database after the placeholder has been substituted, and it means named placeholders can be used. It's worth mentioning that the above syntax is for Oracle - in MySQL the syntax is `LIKE CONCAT('%', :something, '%')`. Reference: http://stackoverflow.com/a/661207/201648 – Aaron Newton Apr 21 '15 at 12:59
  • 1
    This did not work for me exactly, but got me on the right track. I had to do LIKE '%' :something '%' for it to work. – Christopher Smit Jun 17 '17 at 09:58
  • 2
    i know this is off-topic but i was able to peform sql injection with even using this statment, why? – Thiago Dias Jan 10 '18 at 02:13
  • This didn't work for me, I also tested it with SQL command `SELECT * FROM calculation WHERE ( email LIKE '%' || luza || '%' OR siteLocation LIKE '%'|| luza ||'%' OR company LIKE '%' ||luza ||'%' )` this would give me error. – Luzan Baral Oct 26 '18 at 14:28
  • 1
    @AaronNewton `and it means named placeholders can be used`. How it's even an issue with named placeholders when you concatenate in PHP? Obviously concatenating in PHP supports both named and positional and more portable as you can use the same query for any database. I don't really understand why so many people think there is *any* difference between named and positional placeholders. – Your Common Sense Feb 02 '20 at 08:51
20
$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';
}
George G
  • 7,443
  • 12
  • 45
  • 59
Blazer
  • 14,259
  • 3
  • 30
  • 53
  • 1
    Is there any advantage of using this over the accepted answer? Does using `bindValue` protect against injection attacks? The accepted answer basically negates the value of using `?` placeholders by concatenating the search string to `%` like in ye days of olde. – felwithe May 15 '15 at 13:40
  • What is the point of using negation before the $query->rowCount() == 0 ? Does this actually make sense? – ssi-anik Jul 04 '15 at 14:30
17

You can also try this one. I face similar problem but got result after research.

$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);
josliber
  • 43,891
  • 12
  • 98
  • 133
Vijaysinh Parmar
  • 897
  • 1
  • 15
  • 19
  • I edited your post to put the code into a code block -- you can read more about post formatting at http://stackoverflow.com/help/formatting. Some other user chose to downvote your answer without leaving a comment, so I'm not sure about the cause of the downvote. – josliber Sep 27 '15 at 14:39
5

This works:

search `table` where `column` like concat('%', :column, '%')
kjdion84
  • 9,552
  • 8
  • 60
  • 87
3

I got this from php delusions

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

And it works for me, very simple. Like he says , you have to "prepare our complete literal first" before sending it to the query

gavin stanley
  • 1,082
  • 2
  • 13
  • 28
0

PDO escapes "%" (May lead to sql injection): The use of the previous code will give the desire results when looking to match partial strings BUT if a visitor types the character "%" you will still get results even if you don't have anything stored in the data base (it may lead sql injections)

I've tried a lot of variation all with the same result PDO is escaping "%" leading unwanted/unexcited search results.

I though it was worth sharing if anyone has found a word around it please share it

Ozkar R
  • 19
  • 3
  • 1
    This is from the Manual: http://us3.php.net/manual/en/pdo.prepared-statements.php This is another post where about the subject: http://stackoverflow.com/questions/22030451/php-pdo-like-escaping-the-character-when-combining-with-wildcard I owuld really like to know your opinion about this issu. – Ozkar R Sep 27 '15 at 00:41
  • 1
    Possible solution(No tested) Use **CONCAT**, like:$sql = “SELECT item_title FROM item WHERE item_title LIKE CONCAT(‘%’,?,’%’)”; Reference: http://blog.mclaughlinsoftware.com/2010/02/21/php-binding-a-wildcard/ – Ozkar R Sep 27 '15 at 01:37
  • 3
    PDO doesn't escape %. It's your code that does it wrong. For the solution you are are supposed to **read answers already provided here** – Your Common Sense Sep 27 '15 at 08:34
  • Thanks you for you suggestions. Anyway the code tested was the code from the manual, using placeholder to avoid SQL injection, I'm still getting the same result **Example #6 Invalid use of placeholder** PDO does escape % using the above code, not my code. I'm new to forum and I may not understand how the process of comment, post and reputation work here, I'll keep it in mind for my next, because based on the previous comment you need reputation to help others or make comments. thanks. – Ozkar R Sep 27 '15 at 14:52
0

I had a similar need but was using a variable grabbed from a form. I did it like this to get results from my PostgreSQL DB, using PHP:

<?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>";
     }
?>

The "ILIKE" makes the search non-case sensitive, so a search for cart or Cart or cARt will all return the same results.

zdarma
  • 37
  • 4
  • 3
    it's literally the same code as in the accepted answer. – Your Common Sense Feb 02 '21 at 18:21
  • Actually, no it's not, there are a differences. If you think they are literally the same answer, you might want to get your eyes checked. – zdarma Feb 02 '21 at 20:33
  • @zdarma I think what he meant is that the code is almost the same and it does not really add that much of new crucial information. If someone sees the accepted answer he could come up with this a second later. It is too obvious. The idea of StackOverflow is that you provide unique answers that are easy to understand and add something of value. You can refer to an other answer and give them credit and then add your own ideas to it (Given X's solution I would like to change/add x, y, z, reasons). Once you have 50+ rep. you can write comments under the post to critic or add your thoughts. – F. Müller Feb 03 '21 at 06:35
  • 1
    Please highlight the differences to the other answers such that others can learn from it – Nico Haase Feb 03 '21 at 07:50
-2

The only way I could get this to work was to put the %$search% into another variable.

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

I don't know if this is the best way to do it, in the while loop I used:

while ($r = $stmt->fetch(PDO::FETCH_ASSOC)){
MrT2022
  • 11
  • 1