0

I´m trying to put together the most elegant way of searching in two fields for multiple (number of words can vary) terms that needs to only provide results when all words are found (AND instead of OR).

The below gives me an SQL syntax error message:

$search = $_GET["search"];
$searcharray = explode('|', $search);
$query=("SELECT username,sender,message,subject,timestamp,threadid,msgtype 
FROM Messages WHERE  ('" . implode("'|'",$searcharray) . "') IN CONCAT 
(message,subject)  ORDER BY timestamp");

I could of course set up a foreach loop for each match on the first word that breaks with an instruction to not add the result if any of the other words are not found in the two fields, but that´s alot more for the PHP script to handle, I think. Any suggestions?

4
  • What is the full error message you are getting? It should explain what is causing the problem. I have a feeling it's where you implode the array. I think you will need to have one item in the where clause for each item in the search array. Commented Jun 10, 2017 at 0:15
  • You aren't using a regex here, do you mean to be? You are open to SQL injections. You would probably be best off using the full text searching. Commented Jun 10, 2017 at 0:18
  • IN needs to be followed by a literal list of values. Commented Jun 10, 2017 at 0:18
  • No, if only regexp had AND and not only OR I´d be using that. Commented Jun 10, 2017 at 0:42

2 Answers 2

1

IN has to be followed by a list of values in parentheses, or a SELECT subquery. You can't use it for pattern matching.

To search a column for a word, you need to use LIKE, with % around the word. And there's no shortcut for searching for multiple words, you have to search for each of them and combine them with AND.

$tests = array_map(function($word) {
    return "CONCAT(message, subject) LIKE '%$word%'";
}, $searcharray);
$where = implode(' AND ', $tests);
$query = "SELECT username,sender,message,subject,timestamp,threadid,msgtype 
        FROM Messages WHERE $where ORDER BY timestamp";
Sign up to request clarification or add additional context in comments.

5 Comments

Thanks, but this one gave me an Internal Server Error.
Typo, missing parenthesis.
Also used the wrong variable, it should be $searcharray, not $search.
This worked, thanks! Any reason to think that this solution is faster or slower than the one provided by Sloan?
They're basically the same, except he left out the % characters, so it won't work.
1

As mentioned in the comments, the code is suseptable to SQL injection. That being said, and since I don't want to re-write all of the code ;-), here's one way to construct the where clause.

$search = $_GET["search"];
$searcharray = explode('|', $search);
$qstr = "SELECT
    `username`,
    `sender`,
    `message`,
    `subject`,
    `timestamp`,
    `threadid`,
    `msgtype`
FROM `Messages`
WHERE ";
$w = array();
foreach($searcharray as $key => $val) {
    $w[] = "CONCAT(`message`,`subject`) LIKE '%" . $val . "%'";
}
$w_str = implode(" AND ",$w);
$qstr .= $w_str . " ORDER BY `timestamp`";

5 Comments

Thanks, but I get an error here: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '(searchmessage,subject) LIKE 'test' AND CONCAT(searchmessage,`s' at line 10
You need a space after WHERE.
You also need to add % characters around $val.
Ok, with the space I get no results but no error. I get why you need the % wildcard there as you would need it for LIKE to work, but $w[] = "CONCAT(message,subject) LIKE '" . %$val% . "'"; gives me an internal server error.
@CoreyHart The % have to be in the string: LIKE '%" . $val . "%'"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.