I've already checked answers to questions like this one (How do I create a PDO parameterized query with a LIKE statement in PHP).
I've ended up to this solution:
$sql = "SELECT count(*) ".
"FROM mytable ".
"WHERE num_certif LIKE CONCAT('%',:val,'%')";
$valeur = 'azert';
$stmt = $pdo->prepare($sql);
$stmt->bindValue(':val', $val);
This works, but here is my problem: how do I handle the '%' char? (i.e. $valeur = '%'; returns all the rows)?
You need to escape the % character,
$valeur = '\%';
Note for PostgreSQL users... instead of the CONCAT function you can use
SELECT count(*)
FROM mytable
WHERE num_certif LIKE '%' || :val || '%'
I achieved that using string comparison functions:
WHERE INSTR(LCASE(num_certif),LCASE(:val))>0
I suspect performance will suffer.
I have been using something very simple, like this:
$select_str = "SELECT * FROM table_x WHERE text_field LIKE '%".$value."%'";
$StHandler = $this->dbHandler->prepare($select_str);
$StHandler->execute();
You can use only one % depending on what you're looking for. For example, if you want it to start with your value and have any characters later, you will use '".$value."%'"
Hope this helps
In order to avoid having to do your own escaping, the stuff that needs to be escaped has to be part of the data that pdo protects, namely the bound arguments. It doesn't protect you from anything in the hard coded query.
$sql = "SELECT count(*) ".
"FROM avs_souscript ".
"WHERE num_certif =\"\" ".
"AND date_annul=\"\" ".
"AND user=:sess_user ".
"AND user!=\"\" ".
"AND num_certif LIKE :num_certif_search";
$valeur = 'azert'; //I assume this actually came from some user input
$stmt = $pdo->prepare($sql);
$stmt->bindValue(':num_certif_search', '%'.$valeur.'%');
(or alternately you could put them in the $valuer = "%{$userInput}%"; assignment, either way, they should be in the bound argument, not in the sql.
Moving this bit of silly string concat from the sql out to the php is also good practice for making a scalable application. It's much easier to scale a farm of web servers than it is to scale the database server.
Related
I tried to make a search system which uses the LIKE operator to search results based on what the user typed. I'm using it with strings. The problem is that it doesn't show any result.
I hope this also helps people with the same confusion as me...
Code:
"SELECT * FROM table WHERE name LIKE ' . $input . ';";
input is a PHP variable from what the user typed.
EDIT: Don't worry about SQL injection, it's all offline.
for the proper use of like you should use wildchar eg :
SELECT * FROM table WHERE name LIKE concat('%', ? ,'%') ;
and you should not use var inside SQL code .. you are at risk for sqlinjectiomn
for avoid this you should take a look at you db driver for prepared statement and binding param
eg for PDO
$st = $conn->prepare("SELECT * FROM table WHERE name LIKE concat('%', ? ,'%')");
$st->bindParam(1, $input, PDO::PARAM_STR, 255);
$st->execute();
Try This
$string = "input";
$sql = "select * from table where name like '%$string%'"
Create a variable and store value what you want to search
$where = "AND name like '%$string%'";
and put it after table name
$sql = "select * from table_name $where";
The last time I have posted a question about searching JSON data using PHP. After testing the script I wanted to try something else. Using MySQL to search through the data. Since it is faster than looping everything using a PHP script.
I was writing the script in PhpMyAdmin and that has generated the next PHP script for me. But somewhere there is a bug (sad)
"SELECT *
FROM `bigtree_pages`
WHERE `resources` like \'%\"XNCatDesc\": \"%?%\' and `resources` like \'%\"Brand\": \"%?%\' and `resources` like \'%\"ItemDesc\": \"%?%\'"
I want to give three values. The Categorie, the brand, and the ItemDesc (the name). But this throws an error.
You have an error in your SQL syntax; check the manual that
corresponds to your MariaDB server version for the right syntax to use
near '\'%"XNCatDesc": "%'41'%\' and resources like \'%"Brand":
"%'none'%\' and `reso'
To be honest, I don't really know where I have to put my % sign.
For example. I have this in my JSON "Brand": "Bullet",
The value needs to be Brand (since we are searching on the Brand) and the brand is Bullet. What is the best way to write this query?
To use a parameter inside a LIKE expression in a prepared query, you need to form the entire expression and use that as the parameter. Otherwise you run into issues as you have with the insertion of quotes into your value. If you are using mysqli, try something like this (assuming your connection is called $conn and the values you want to search for are called $categorie, $brand and $itemdesc):
$stmt = $conn->prepare("SELECT *
FROM `bigtree_pages`
WHERE `resources` like ? and `resources` like ? and `resources` like ?");
$search_categorie = "%\"XNCatDesc\": \"%$categorie%\"";
$search_brand = "%\"Brand\": \"%$brand%\"";
$search_itemdesc = "%\"ItemDesc\": \"%$itemdesc%\"";
$stmt->bind_param("sss", $search_categorie, $search_brand, $search_itemdesc);
$stmt->execute();
However the problem you will run into is that because of the % surrounding the search values (e.g. $brand) in the query, when searching for brand = X you could match for example
"Brand": "Y", "Other Value": "contains an X"
So instead you should use regular expressions e.g.
$stmt = $conn->prepare("SELECT *
FROM `bigtree_pages`
WHERE `resources` rlike ? AND `resources` rlike ? AND `resources` rlike ?");
$search_categorie = '"XNCatDesc":[[:space:]]+"[^"]*' . $categorie;
$search_brand = '"Brand":[[:space:]]+"[^"]*' . $brand;
$search_itemdesc = '"ItemDesc":[[:space:]]+"[^"]*' . $itemdesc;
$stmt->bind_param("sss", $search_categorie, $search_brand, $search_itemdesc);
$stmt->execute();
If you are running MySQL 5.7 or later, this is better done using the inbuilt JSON_EXTRACT function:
$stmt = $conn->prepare("SELECT *
FROM `bigtree_pages`
WHERE JSON_EXTRACT(`resources`, '$.XNCatDesc') LIKE ? and
JSON_EXTRACT(`resources`, '$.Brand') LIKE ? and
JSON_EXTRACT(`resources`, '$.ItemDesc') LIKE ?");
$search_categorie = "%$categorie%";
$search_brand = "%$brand%";
$search_itemdesc = "%$itemdesc%";
$stmt->bind_param("sss", $search_categorie, $search_brand, $search_itemdesc);
$stmt->execute();
I'm building a script where users can search a database. my understanding is that PDO doesn't let you set a parameter for the LIKE operand. So I have this code to make up for it
$sQuery = "SELECT * FROM table WHERE column LIKE '%" . $this->sQuery . "%' LIMIT 30";
$Statement = $this->Database->prepare($sQuery);
$Statement->execute();
I doubt this is secure against SQL injection. Is there any way to make it secure?
You're right, interpolating any value into an SQL string creates a risk for SQL injection vulnerability. It's better to use a SQL query parameter placeholder when you prepare(), and then supply the value as a parameter when you execute().
$pattern = "%" . $this->sQuery . "%";
$sQuery = "SELECT * FROM table WHERE column LIKE ? LIMIT 30";
$Statement = $this->Database->prepare($sQuery);
$Statement->execute(array($pattern));
Take that as pseudocode because I can't tell from your example which MySQL extension you're using. I'm assuming PDO, which allows parameters to be sent as an array argument to execute().
Some people use PDOStatement::bindParam(), but there's no advantage to doing so. Maybe in some other RDBMS brands the PDO::PARAM_STR matters, but in the MySQL driver, the parameter type is ignored.
PS: Aside from the security issue you asked about, you will find a search for wildcard-based patterns like you're doing don't perform well as your data grows larger. See my presentation Full Text Search Throwdown.
This should work:
$sQuery = "SELECT * FROM table WHERE column LIKE :query LIMIT 30";
$Statement = $this->Database->prepare($sQuery);
$Statement->execute(array(':query' => '%' . $this->sQuery . '%'));
I need to create a select query which fetches records according to multiple variables
like:
<?PHP
#$task=$_REQUEST['task'];
#$Country=$_REQUEST['Country'];
#$City =$_REQUEST['City'];
#$MosqName =$_REQUEST['txtMsqName'];
#$PostCode =$_REQUEST['txtPostalCode'];
$sql_serch="SELECT Country="."'".$Country."'", " City="."'".$City."'"." FROM job_mosqu";
?>
It is not working.
Don't forget to escape your input! NEVER put user-inputted variables (such as those from $_REQUEST) directly into SQL queries. Either use parametrized queries or escape the input using either mysql_real_escape_string, mysqli::real_escape_string or PDO::quote depending on what you're querying with...
Some reading on the subject:
PHP MySQL by example
StackOverflow question on it
Coding Horror
And to answer your actual question, use the WHERE clause.
SELECT * FROM job_mosqu WHERE Country = ? AND City = ? ...
There's plenty to read out there on using the where clause, just do some searching if you're not comfortable with it...
Tutorial on WHERE in mysql
Another Tutorial
And yet another
You are looking for AND
SELECT * FROM job_mosqu WHERE Country='$country' AND City= '$City'
Etc...
SELECT * FROM job_mosqu WHERE Country='$country' AND City= '$City' AND task = '$task' AND $MosqName = '$MosqName';
It is incorrect query. It is very bad query. May be you want next?
$task=$_REQUEST['task'];
$Country =$_REQUEST['Country'];
$City =$_REQUEST['City'];
$MosqName =$_REQUEST['txtMsqName'];
$PostCode =$_REQUEST['txtPostalCode'];
$sql_serch="SELECT `Country`, `City` FROM `job_mosqu` WHERE `City`='" . $City. "' AND `Country`='" . $Country . "'";
I'm letting users search my database for data by city.
My query looks like:
$results = mysql_query("SELECT * FROM mydb WHERE City='".$city."' LIMIT 10");
I want a user to be able to search 'all cities', so I'd like to either remove the WHERE statement if $city=='all cities'; or use a wildcard for the WHERE statement that matches all cities in the db.
I used to have an IF statement that switched between two queries, but I want to add more filters like country/all countries, zipcode/all zipcodes, etc, So I'd rather keep one dynamic SQL query.
Well, you could still have just one query and build the where clause dynamically, as such:
$where = '';
// conditional statements (if/else, switch) for populating the where clause
$where .= " WHERE City = '{$city}'";
$where .= " AND Country = '{$country}'";
$results = mysql_query("SELECT * FROM mydb{$where} LIMIT 10");
One way would be a case statement:
WHERE City = case when '$city' = 'All cities' then City else '$city' end
If the user is searching for 'All cities', this turns the WHERE statement into:
WHERE City = City
Which is always true (at least for non-null cities ;))
P.S. Make sure you're running these queries using a read-only MySQL account. The user could enter funny stuff into the $city parameter!
You could try
WHERE City like '$city'
and permit the users to enter wildcards, if you think they'd be up to it.
although not PHP programmer, this pseudocode might offer an option... conditionally build out your where clause. Additionally, I would do it with parameterized queries instead of direct string building to prevent sql-injection attacks.
cYourSQL = "select * from YourTable where "
cAndRequired = ""
if city is NOT "all cities"
cYourSQL = cYourSQL + cAndRequired + " city = 'YourParameterValueProvided' "
cAndRequired = " AND "
endif
Now, always add your country selection
cYourSQL = cYourSQL + cAndRequired + " country = 'YourCountryValue' LIMIT 10 "
Run the query