SQL search multiple values in same field - mysql

I'm building a simple search algorithm and I want to break my string with spaces, and search my database on it, like so:
$search = "Sony TV with FullHD support";
$search = explode( ' ', $search );
SELECT name FROM Products WHERE name LIKE %$search[1]% AND name LIKE %$search[2]% LIMIT 6
Is this possible?

Yes, you can use SQL IN operator to search multiple absolute values:
SELECT name FROM products WHERE name IN ( 'Value1', 'Value2', ... );
If you want to use LIKE you will need to use OR instead:
SELECT name FROM products WHERE name LIKE '%Value1' OR name LIKE '%Value2';
Using AND (as you tried) requires ALL conditions to be true, using OR requires at least one to be true.

Try this
Using UNION
$sql = '';
$count = 0;
foreach($search as $text)
{
if($count > 0)
$sql = $sql."UNION Select name From myTable WHERE Name LIKE '%$text%'";
else
$sql = $sql."Select name From myTable WHERE Name LIKE '%$text%'";
$count++;
}
Using WHERE IN
$comma_separated = "('" . implode("','", $search) . "')"; // ('1','2','3')
$sql = "Select name From myTable WHERE name IN ".$comma_separated ;

This will works perfectly in both cases, one or multiple fields searching multiple words.
Hope this will help someone. Thanks
declare #searchTrm varchar(MAX)='one two three four';
--select value from STRING_SPLIT(#searchTrm, ' ') where trim(value)<>''
select * from Bols
WHERE EXISTS (SELECT value
FROM STRING_SPLIT(#searchTrm, ' ')
WHERE
trim(value)<>''
and(
BolNumber like '%'+ value+'%'
or UserComment like '%'+ value+'%'
or RequesterId like '%'+ value+'%' )
)

This has been partially answered here:
MySQL Like multiple values
I advise against
$search = explode( ' ', $search );
and input them directly into the SQL query as this makes prone to SQL inject via the search bar. You will have to escape the characters first in case they try something funny like: "--; DROP TABLE name;
$search = str_replace('"', "''", search );
But even that is not completely safe. You must try to use SQL prepared statements to be safer. Using the regular expression is much easier to build a function to prepare and create what you want.
function makeSQL_search_pattern($search) {
search_pattern = false;
//escape the special regex chars
$search = str_replace('"', "''", $search);
$search = str_replace('^', "\\^", $search);
$search = str_replace('$', "\\$", $search);
$search = str_replace('.', "\\.", $search);
$search = str_replace('[', "\\[", $search);
$search = str_replace(']', "\\]", $search);
$search = str_replace('|', "\\|", $search);
$search = str_replace('*', "\\*", $search);
$search = str_replace('+', "\\+", $search);
$search = str_replace('{', "\\{", $search);
$search = str_replace('}', "\\}", $search);
$search = explode(" ", $search);
for ($i = 0; $i < count($search); $i++) {
if ($i > 0 && $i < count($search) ) {
$search_pattern .= "|";
}
$search_pattern .= $search[$i];
}
return search_pattern;
}
$search_pattern = makeSQL_search_pattern($search);
$sql_query = "SELECT name FROM Products WHERE name REGEXP :search LIMIT 6"
$stmt = pdo->prepare($sql_query);
$stmt->bindParam(":search", $search_pattern, PDO::PARAM_STR);
$stmt->execute();
I have not tested this code, but this is what I would do in your case.
I hope this helps.

You can try and execute below query:
SELECT name FROM Products WHERE REGEXP '.*Value1|.*Value2';
Pls note that there should not be a space before or after the pipe symbol
(|).

I know this is long time ago, but I have a solution. It can solved like this:
#intial query
query = 'SELECT var1, var2 FROM dbo.db_name WHERE'
if status :
query = query + " AND status='" + status + "'"
if type :
query = query + " AND Type='" + type + "'"
if number :
query = query + " AND Number='" + number + "'"
if cancel_request:
query = query + " AND CancelRequest='" + cancel_request + "'"
query = query + ' ORDER BY transid DESC'
cur.execute(query)

Related

left statement doesn't work properly in mysql

I used left statement and Locate to fet substring of some field in database to do (Show more). It is working properly but sometimes it's not working right.
This is the code :
function split_field($table = "d_book", $field = "bo_about", $length = 195) {
$tbl_field = "TRIM(".$table.".".$field.")";
$sql = "CONCAT(LEFT({$tbl_field}, IF(LENGTH({$tbl_field}) > {$length}, LOCATE(' ', {$tbl_field}, {$length}), {$length})),
IF(LENGTH({$tbl_field}) > {$length}, '...', ''))
AS `{$field}`";
return $sql;
}
$sql = "SELECT `bo_price`,`bo_id`, `bo_au_id`,`bo_name`,";
$sql .= split_field();
$sql .=",`bo_cover_img`, `bo_num_pages`, `d_book`.`bo_sec_id`, `d_section`.`sec_id`, `d_author`.`au_id`, `d_author`.`au_name`
FROM (`d_book`)
JOIN `d_section` ON `d_section`.`sec_id`=`d_book`.`bo_sec_id`
JOIN `d_author` ON `d_author`.`au_id`=`d_book`.`bo_au_id`
WHERE `d_book`.`bo_state` = '1'";
$sql .= " ORDER BY `d_book`.`bo_ord` DESC LIMIT $start_limit,20";
The problem is that some books that have string less than 195 don't appear totally.
Tip: all strings in arabic language

PHP explode and MySQL query to search in multiple columns

I have a form where I want a user to enter one or more words. These words should then match mutiple columns in a MySQL database.
I have started to build some code but I'm stuck.
<?php
$term = $_SESSION['session_searchstring']; //Let's say that session is John Doe
$searchterm = explode(' ',$term);
$searchFieldName = "name";
$searchCondition = "$searchFieldName LIKE '%" . implode("%' OR $searchFieldName LIKE '%", $searchterm) . "%'";
$sql = "SELECT * FROM students WHERE $searchCondition;";
echo $sql; //Echo to test what mysql_query would look like
?>
The above code will output:
SELECT * FROM students WHERE name LIKE '%John%' OR name LIKE '%Doe%';
The problem is that I want to search in multiple columns ($searchFieldName). I have for example
customer_firstname
customer_lastname
And I want to match my searchstring against the content of both columns.. How would I continue?
Perhaps
$term = $_SESSION['session_searchstring']; //Let's say that session is John Doe
$searchterm = explode(' ',$term);
$searchColumns = array("customer_firstname","customer_lastname");
for($i = 0; $i < count($searchColumns); $i++)
{
$searchFieldName = $searchColumns[$i];
$searchCondition .= "($searchFieldName LIKE '%" . implode("%' OR $searchFieldName LIKE '%", $searchterm) . "%')";
if($i+1 < count($searchColumns)) $searchCondition .= " OR ";
}
$sql = "SELECT * FROM students WHERE $searchCondition;";
echo $sql; //Echo to test what mysql_query would look like
Produces
SELECT * FROM students WHERE (customer_firstname LIKE '%John%' OR customer_firstname LIKE '%Doe%') OR (customer_lastname LIKE '%John%' OR customer_lastname LIKE '%Doe%');
If your table is of MyIsam type or you can convert it to MyIsam, use MySQL Fulltext Search. if not, anyway, you can build a long query like
SELECT * FROM students WHERE name LIKE '%John%' OR name LIKE '%Doe%' OR lastname LIKE "%John%" OR lastname LIKE "%Doe%"
or union your columns into one another just for search (but this both are not prefered).
Also a good approach is to use fulltext search engines like Sphinx.
In my case I needed all search phrases/terms to match at least one column, no search phrase/term could be a no-match.
I ended up tweaking the example from Kermit in the following way:
public function getRawWhereFilterForColumns($filter, $search_columns)
{
$search_terms = explode(' ', $filter);
$search_condition = "";
for ($i = 0; $i < count($search_terms); $i++) {
$term = $search_terms[$i];
for ($j = 0; $j < count($search_columns); $j++) {
if ($j == 0) $search_condition .= "(";
$search_field_name = $search_columns[$j];
$search_condition .= "$search_field_name LIKE '%" . $term . "%'";
if ($j + 1 < count($search_columns)) $search_condition .= " OR ";
if ($j + 1 == count($search_columns)) $search_condition .= ")";
}
if ($i + 1 < count($search_terms)) $search_condition .= " AND ";
}
return $search_condition;
}
I only needed the contents of the Where-clause since I'm using Laravel and could put that into the rawWhere-method.
usage:
$search_condition = $this->getRawWhereFilterForColumns
("John Doe", array("column1", "column2"));
which produces
(column1 LIKE '%John%' OR column2 LIKE '%John%')
AND (column1 LIKE '%Doe%' OR column2 LIKE '%Doe%')
And finally you use this $search_condition in whatever way suits you, for example:
$sql = "SELECT * FROM students WHERE $search_condition;";
Or in my Laravel-case:
$modelInstances = Model::whereRaw
($search_condition)->paginate(self::ITEMS_PER_PAGE);
Perhaps this is an improved solution for either David or anybody else visiting this thread, like me, even if it's almost two years after the original post.

mySQL breaks when adding a var

I'm attempting to modify a mySQL query (that works) to return a more specific result. I've added a variable to the statement so that it looks for jobID AND UserName. Adding the $userName to the statement breaks it.
I've included the code below with the three variations of the SQL statement for comparison. I'm sure it's something obvious - to everyone but me...
Thanks in advance!
DB
// get all applicants from a User
public function GetAllMyApplications($from=false, $to=false, $user_name)
{
global $db;
$applicants = array();
if ($from >= 0 && $to > 0)
{
$sql_limit = ' LIMIT ' . $from .', ' . $to;
}
else
{
$sql_limit = '';
}
$user_name = "Bob Bobberton"; // reset this var for testing
$sql = 'SELECT * FROM '.DB_PREFIX.'job_applications WHERE job_id = '. $this->mJobId . ' ORDER BY name ASC ' . $sql_limit; // This was the original SQL that worked
$sql = 'SELECT * FROM '.DB_PREFIX.'job_applications WHERE job_id = '. $this->mJobId . ' AND name = ' . $user_name . ' ORDER BY name ASC ' . $sql_limit; // Added "and" $user_name - it breaks
$sql = 'SELECT * FROM '.DB_PREFIX.'job_applications WHERE job_id = '. $this->mJobId . ' AND name = "Bob Bobberton" ORDER BY name ASC ' . $sql_limit; // Replace var with value "Bob Bobberton" and it works
$result = $db->query($sql);
while ($row = $result->fetch_assoc())
{
$applicants[] = array('id' => $row['id'],
'job_id' => $row['job_id'],
'name' => $row['name'],
'email_address' => $row['email_address'],
'message' => str_replace(array("\r\n", "\r", "\n"), "<br />", $row['message']),
'resume_path' => base64_encode($row['resume_path']),
'created_on' => $row['created_on'],
'ip' => $row['ip']);
}
if (isset($applicants))
{
return $applicants;
}else{
return("");
}
}
change this
' AND name = ' . $user_name . ' ORDER BY name ASC '
to
" AND name = '" . $user_name . "' ORDER BY name ASC "
and it will work
The solution provided by Satya is not enough. You should escape your inputs properly.
Assume your $username contains a " character. That will break your SQL statement. So you should use prepared statements or, at least, use the function mysql_real_string_escape().

MySql LIKE returns false if search term is same as entire string in the column, why is that?

So I have following as part of my query
SELECT * FROM $table WHERE columname LIKE '%$searchterm%'
I have tried taking out leading and/or ending wildcards meaning
SELECT * FROM $table WHERE columname LIKE '$searchterm%'
AND
SELECT * FROM $table WHERE columname LIKE '%$searchterm'
AND
SELECT * FROM $table WHERE columname LIKE '%$searchterm%' OR columname LIKE '$searchterm'
and also tried adding following to the query with no luck
OR columname = '$searchterm'
So when my search term is "myval" and if column has whole string "myval", I would like to have that selected. But ALL of my queries above, return false/return nothing where myval is searchterm and column value as full.
I can not use MATCH because this is not Full-Text index.
EDIT:
PHP Code:
$sterm = NULL;
$table = 'mytable';
if(isset($_GET['s'])) { $sterm = explode(" ", mysql_real_escape_string($_GET['s'])); }
if(isset($_POST['s'])) { $sterm = explode(" ", mysql_real_escape_string($_POST['s'])); }
if(!empty($sterm)){
$getdata = "SELECT * FROM $table WHERE termsi != 'Special' ";
foreach ($sterm as $value){
$getdata .= "AND netid_all LIKE '%$value%' OR netid_all = '$value' ";
} //End foreach
$getdata .= "LIMIT 10";
$result = mysql_query($getdata) or die(mysql_error());
$row = mysql_fetch_array($result, MYSQL_ASSOC);
while($row = mysql_fetch_array($result, MYSQL_ASSOC))
{
echo <<<PRINTALL
{$row[0]}, {$row[1]}, {$row[2]}, {$row[3]}, {$row[4]}, {$row[5]}, {$row[6]}, {$row[7]}, ' <br />'
PRINTALL;
} //End While
} //End If search exists
Okay So As you guys suggested, i tried PHPMyAdmin sql console and it works fine, so it would have to be by PHP!? so here it is.
I'd suggest writing your query building like this:
$fullvalues = array();
$partials = array();
foreach ($sterm as $value){
$partials[] = "(netid_all LIKE '%" . mysql_real_escape_string($value) . "%')";
$fullvalues[] = "'" . mysql_real_escape_string($value) . "'";
}
$partials = implode(' OR ', $partials);
$fullvalues = implode(', ', $fullvalues);
$sql = <<<EOL
SELECT *
FROM $table
WHERE (termsi != 'Special')
AND (($partials) OR (netid_all IN ($fullvalues));
EOL;
Assuming your search string is a b c, you'd get this query:
SELECT *
FROM yourtable
WHERE (termsi != 'Special')
AND (((netid_all LIKE '%a%') OR (netid_all LIKE '%b%') OR (netid_all LIKE '%C%')) OR (netid_all IN ('a', 'b', 'c')))
If your search requires that all terms be present, then change the 'OR' to 'AND' in the implode.
Well found it,
$row = mysql_fetch_array($result, MYSQL_ASSOC);
while($row = mysql_fetch_array($result, MYSQL_ASSOC))
Was the problem, earlier when I was testing things, anyhow, it should have been the following
$row = mysql_fetch_array($result, MYSQL_ASSOC);
while($row)

MYSQL query for searching through ALL the fields?

As dumb as it sounds, is there a way to do something like this:
select row_id from mytable where * like '%searched_text%';
By * here I mean "all the fields" in the table, instead of me specifying them one by one...
It is not possible with one query.
However when you do:
DESCRIBE table_name;
you get the field names which you can generate the query from.
Search in all fields from every table of a MySQL database May be useful.
Here's a solution combined with some PHP to search all fields in a specific table.
include("db_con.php");
//search all fields
$searchphrase = "banan";
$table = "apa303";
$sql_search = "select * from ".$table." where ";
$sql_search_fields = Array();
$sql = "SHOW COLUMNS FROM ".$table;
$rs = mysql_query($sql);
while($r = mysql_fetch_array($rs)){
$colum = $r[0];
$sql_search_fields[] = $colum." like('%".$searchphrase."%')";
}
$sql_search .= implode(" OR ", $sql_search_fields);
$rs2 = mysql_query($sql_search);
$out = mysql_num_rows($rs2)."\n";
echo "Number of search hits in $table " . $out;
Yes, it's called Full Text Search.
You can use MySQL's built-in Full Text Search, or use a separate product to do you text indexing such as Apache's Lucene (my personal favorite).
I was looking something like this to search in all the fields of a table. Though my table having less data so I opted 'Kilian Lindberg' answer and make the PDO function using his idea. In this function we can sent the 'search string' and 'Table name' in parameter and it will return the SQL string which we can use further as per our requirement. Thought in big tables it may slowdown the process.
function columnsTable($Search, $Table){
include("PDO_conn_detail.php"); /* your PDO mysql connection file */
$srchSQLstr = "SELECT * FROM $Table WHERE ";
$tableFields = Array();
$colSQL = $conn->prepare("SHOW COLUMNS FROM $Table");
$colSQL->execute();
while ($result_colSQL = $colSQL->fetch(PDO::FETCH_ASSOC)){
$tableFields[] = $result_colSQL[Field]." LIKE ('%".$Search."%')";
}
$srchSQLstr .= implode(" OR ", $tableFields);
return $srchSQLstr;
}
Use like this
select row_id from mytable where '%searched_text%' IN ('column1','column2','column3','column4','column5');
This solution make it possible by Ms Sql Server via Linked server
DECLARE #searchTxt VARCHAR(100) = 'searching text'
DECLARE curr CURSOR LOCAL FAST_FORWARD READ_ONLY FOR
select * from openquery (BITRIX, 'SELECT table_name, column_name FROM information_schema.columns where table_schema = ''bitrix_50'' and data_type = ''varchar'' and table_name not like ''b_mail%''')
DECLARE #tName VARCHAR(100), #cName VARCHAR(100), #sql NVARCHAR(4000), #cnt INT
OPEN curr
FETCH NEXT FROM curr INTO #tName, #cName
WHILE (##FETCH_STATUS=0)
BEGIN
SET #sql = 'select #cnt=cnt from openquery (BITRIX, ''SELECT count(*) cnt FROM ' + #tName + ' WHERE ' + #cName + ' LIKE ''''%' + #searchTxt + '%'''''')'
BEGIN TRY
EXECUTE sp_executesql #sql, N'#cnt int OUTPUT', #cnt=#cnt OUTPUT
IF (#cnt>0)
PRINT #sql
END TRY
BEGIN CATCH
PRINT N'Error on: ' + #sql
END CATCH
FETCH NEXT FROM curr INTO #tName, #cName
END
CLOSE curr
DEALLOCATE curr
Access MySQL data from SQL Server via a Linked Server
He is a complete solution,,is the modification of the above solution,It worked for me, Thank you.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title></title>
</head>
<body>
<?php
include('config.php');
$searchphrase = "adsa";
$table = "tenders";
$sql_search = "select * from " . $table . " where ";
$sql_search_fields = Array();
$sql = "SHOW COLUMNS FROM " . $table;
$rs = mysql_query($sql);
while ($r = mysql_fetch_array($rs)) {
$colum = $r[0];
$sql_search_fields[] = $colum . " like('%" . $searchphrase . "%')";
}
$sql_search .= implode(" OR ", $sql_search_fields);
$rs2 = mysql_query($sql_search);
$out = mysql_num_rows($rs2) . "\n";
echo "Number of search hits in $table " . $out."<br />";
while ($results = mysql_fetch_array($rs2)){
print $results[0]."<br />";
}
?>
</body>
</html>