427

I've been trying to figure out how I can make a query with MySQL that checks if the value (string $haystack ) in a certain column contains certain data (string $needle), like this:

SELECT *
FROM `table`
WHERE `column`.contains('{$needle}')

In PHP, the function is called substr($haystack, $needle), so maybe:

WHERE substr(`column`, '{$needle}')=1
0

8 Answers 8

609

Quite simple actually:

SELECT *
FROM `table`
WHERE `column` LIKE '%{$needle}%'

The % is a wildcard for any characters set (none, one or many). Do note that this can get slow on very large datasets so if your database grows you'll need to use fulltext indices.

Sign up to request clarification or add additional context in comments.

10 Comments

This will only work if your using a prepared query. If you're using an actual string in there (ex. liquibase sql upgrade script) then consider INSTR mentioned below). This is because if your string contains a % then you'll start matching things with it to.
i know about like queries, and yet today i wanted to find out if certain value exist in string in some column i was googling for it.. Why i never thought of it before??
is this case sensitive?
@angry_kiwi: with column LIKE '...' it is case insensitive, with column LIKE BINARY '...' it is case sensitive
I'm surprised that LIKE is proposed to check for any substring since this operator uses two wildcard characters : % and _. This mean if your string $needle contains one of this special characters then the results is not as expected at all. (-1) for this reply, and (+1) for the INSTR reply.
|
217

Use:

SELECT *
  FROM `table`
 WHERE INSTR(`column`, '{$needle}') > 0

Reference:

5 Comments

surely LIKE is faster than INSTR?
@oedo: Depends. LIKE %...% won't use an index if one is present, so they should be equivalent; LIKE ...% would use an index if present. If performance is a real concern, Full Text Search (FTS) would be a better approach.
perfect. just what I've been looking for.
I like this solution as in fact there is no way to sort things according to the presence of a substring with like operator . With instr a phrase can be ordered like this select * from table order by instr(col1,"mystring")
I wanted to search for _ in a field and it worked. Thanks
72
WHERE `column` LIKE '%$needle%'

2 Comments

when searching for the character _ (underscore) the query LIKE '%_%' doesn't work, for some reason it returns all strings even without _
@Wojtek _ is a wildcard for any single character, so if you want to search for a literal underscore you will need to escape it. See MySQL LIKE query with underscore.
52

Mine is using LOCATE in mysql:

LOCATE(substr,str), LOCATE(substr,str,pos)

This function is multi-byte safe, and is case-sensitive only if at least one argument is a binary string.

In your case:

SELECT * FROM `table`
WHERE LOCATE('{$needle}', `column`) > 0

3 Comments

'column' should be column (without quotes)
'column' should not be in backticks, right?
@ValterEkholm, No. backticks are the normal way to denote an entity in MySQL. (Like a schema, table, table-alias, column, etc.) They're especially useful when you have a column named something that's a keyword or very common/ambiguous term (e.g. DateTime, Date, Status, Name, etc). Wrapping them in backticks makes it explicitly clear that it's an entity, and not a keyword/function/etc.
14

In addition to the answer from @WoLpH.

When using the LIKE keyword you also have the ability to limit which direction the string matches. For example:

If you were looking for a string that starts with your $needle:

... WHERE column LIKE '{$needle}%'

If you were looking for a string that ends with the $needle:

... WHERE column LIKE '%{$needle}'

Comments

5

You probably are looking for find_in_set function:

Where find_in_set($needle,'column') > 0

This function acts like in_array function in PHP

Comments

4

be aware that this is dangerous:

WHERE `column` LIKE '%{$needle}%'

do first:

$needle = mysql_real_escape_string($needle);

so it will prevent possible attacks.

2 Comments

*Some possible attacks. Also, mysql_real_escape_string is going to be deprecated in future PHP releases.
You should use prepared statements, and leave the escaping to PHP. $stmt = $dbh->prepare("Where 'column' LIKE '{:needle}'"); $stmt->bindParam(':needle', $needle); $stmt->execute();
-5

The accepted answer would be correct for MySQL alone, but since the question is using:

  • a variable,
  • appears to be using {$needle} as a replacement tag, and
  • it mentions PHP

it appears the author wanted to construct the MySQL query using PHP.

Since the question was asked 12 years ago, current practice would be to use preprepared statements to prevent SQL injection.

Here is an example with PHP:

function check_connection ($user, $pass, $db = 'test', $host = '127.0.0.1', $charset = 'utf8mb4') {
     if (isset($GLOBALS['conn']) && is_object($GLOBALS['conn']) && ($GLOBALS['conn'] instanceof PDO)) {
          if (same_database($db) === true) {
               $connection = &$GLOBALS['conn']; 
          }
          else {
               $GLOBALS['conn'] = pdo_connect($user, $pass, $db, $host, $charset);
               $connection = &$GLOBALS['conn'];       
          }
     }
     else {
          $GLOBALS['conn'] = pdo_connect($user, $pass, $db, $host, $charset);
          $connection = &$GLOBALS['conn'];
     }

     return $connection;
}

function pdo_connect ($user, $pass, $db, $host, $charset){    
     $dsn = "mysql:host=$host;dbname=$db;charset=$charset";
     $options = [
       PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
       PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
     ];
     try {
       return new PDO($dsn, $user, $pass, $options);
     } 
     catch (\PDOException $e) {
       throw new \PDOException($e->getMessage(), (int)$e->getCode());
     }
}

function same_database($db) {
    if (isset($GLOBALS['conn']) && is_object($GLOBALS['conn']) && ($GLOBALS['conn'] instanceof PDO)) {
        $sql = "SELECT DATABASE() AS 'database'";
        $sth = $GLOBALS['conn']->prepare($sql);
        $sth->execute();
        if (strcasecmp(trim($sth->fetchAll(PDO::FETCH_ASSOC)['0']['database']), trim($db)) === 0) { 
            return true;
        }
    }

    return false;
}
    
$conn = check_connection($user, $pass, $db, $host, $charset);

$sql = "
     SELECT *
     FROM `table`
     WHERE `column` like :needle
";

// Concatenating the % wildcard before and after our search variable
$bind = array(
     ':needle' => '%'.$needle.'%'
);

$sth = $conn->prepare($sql);
$sth->execute($bind);

// Being redundant about fetch_assoc incase it was not set in pdo() options
$result = $sth->fetchAll(PDO::FETCH_ASSOC);

// You would use rowCount(), instead of fetchAll(), if it is NOT a SELECT statement
// $sth->rowCount();

print_r($result);

Here are two resources for building PHP PDO statements:

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.