I need to do this query:
SELECT * FROM brands WHERE brand =`l'artigiano italiano`
Should be quite simple but it's not working.
Like all my queries I try to execute it with the following code
$myDB = Database::getConnection($target='....',$key='....');
$sqlLogo = 'SELECT * FROM brands WHERE brand =`' . $brand->merk . '`';
$resultLogo = $myDB->query($sqlLogo);
When I open the page I get the following error
PDOException: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'l'artigiano italiano' in 'where clause': SELECT * FROM brands WHERE brand =`l'artigiano italiano`; Array ( ) in merken_admin_settings() (line 23 of /home/mediaspe/domains/mediaspex.be/public_html/juniorsteps/sites/all/modules/merken/merken.admin.inc)
I tried to use
WHERE brand = "..."
and
WHERE brand = `...`
but both did not work.
Any suggestions about the possible cause? I'm staring blind at the code at the moment.
You should escape anything you embed in a SQL query. As you are using PDO, you should do it with $myDB->quote():
$sqlLogo = "SELECT * FROM brands WHERE brand = '" . $myDB->quote($brand->merk) . "'";
You can use both double quotes (") and single quotes (') for enclosing your values, but not back quotes (`).
It is even better to use prepared statements:
$stmt = $myDB->prepare("SELECT * FROM brands WHERE brand = :brand");
$resultLogo = $stmt->execute(array('brand' => $brand->merk));
This way you don't have to take care of escaping.
Have you tried escaping the single quote?
"l\'artigiano italiano"
MySQL String Syntax
While all of the other answers are valid for regular mysql_* functions, if you are using PDO, you should be taking advantage of prepared statements. They were made for just this purpose.
Just escaping the single quote can do the trick but try PDO prepared statements, they help you with security too (as already discussed here)
You can do it like this:
$brand = "l'artigiano italiano";
$stmt = $db->prepare('SELECT * FROM brands WHERE brand = :brand');
$stmt->execute( array(':brand' => $brand) );
It looks like you're using Drupal. If that's so (I assume so from the way you get the database connection and obviously the tag), you should execute your query like this:
$result = db_query('SELECT * FROM {brands} WHERE brand = :brand', array(':brand' => $brand));
That's all. Note:
Use of db_query(), which will call Database::getConnection() internally. You only need to call Database::getConnection() yourself if you want to connect to another than the default connection.
Use uf curly braces ({}) for tables managed by Drupal (which means, tables installed through hook_schema() of your module). If this is an external table not related to the Drupal installation, you won't need those. The curly braces ensure that the proper table name prefix is inserted in case the drupal installation was configured with one (which is for example the case when running tests!)
You can use :placeholder syntax for the dynamic values and directly specify the value in the second argument of db_query() (or $myMD->query(), that's the same interface).
Related
Similar questions have been asked many times, but after reading almost every of these for over 5 hours, i have not found a suitable reply for my problem.
Im not an experience php / mysql developer, but i ve managed similar situations with the use of mysqli_stmt_bind_param() func.
Here is the query:
$query = 'SELECT Recipes.* , Categories.* FROM `Recipes` JOIN `Categories` ON JSON_EXTRACT(Recipes.category, \'$.category\') = \'Category ?\' WHERE Categories.category = ?';
I use this php code:
if ($stmt = mysqli_prepare($dbManager->getDBInstance(), $query)){
mysqli_stmt_bind_param($stmt,"ii", $id, $id);
}
Because i have a model on the client side like:
{
"category" : "...",
"recipes" : [{...},{...}]
}
The error is: Fatal error: Uncaught mysqli_sql_exception: No data supplied for parameters in prepared statement
I have already made similar queries with many more parameters, without any error: however, this is the first time i use the JSON_EXTRACT func from mysql.
I believe the error is caused by the $. which is not escaped correctly. The parameters to be replaced reference to the same variable, $id, which is an integer, and gets used for string interpolation in the first case ('Category 1') and as number after the WHERE clause.
Consider that, by not using mysqli_stmt_bind_param, the same query on phpmyadmin returns what i want, but that would open my code to mysql injections, which i want to avoid.
Also, notice that if i pass just one parameter to the function, the script gets executed (with wrong results), like if the query gets truncated at some point... i properly escaped every single quote, and even tried with double quotes, but the error is always the same.
Any hint on how to prevent the injection and achieve the result would be highly appreciated, because i really can't figure it out by myself.
Thank you
You have two parameters in the call to mysqli_stmt_bind_param(), but there's only one placeholder in $query. The first ? is inside quotes, so it's treated literally, not as a placeholder.
You can use CONCAT() to concatenate a string literal with a placeholder, so change it to:
$query = '
SELECT Recipes.* , Categories.*
FROM `Recipes`
JOIN `Categories` ON JSON_EXTRACT(Recipes.category, \'$.category\') = CONCAT(\'Category \', ?)
WHERE Categories.category = ?';
A placeholder can represent a complete data literal only. To put it simple - anything you would write in quotes (or a number). So it shouldn't be 'Category ?' but just ? where Category could be concatenated in PHP.
$query = 'SELECT * FROM `Recipes` JOIN `Categories` ON
JSON_EXTRACT(Recipes.category, \'$.category\') = ?
WHERE Categories.category = ?';
$stmt = mysqli_prepare($dbManager->getDBInstance(), $query);
$category = "Category $id";
mysqli_stmt_bind_param($stmt,"si", $category, $id);
This is bizarre, I'm changing some code from mysql to mysqli functions cause of php 5.5+, in these two basic examples, mysql_query had no ' single quote nor ` backtick and worked fine.
$sql = "SELECT * FROM `".$table."`"; // requires: ` ` or fails
$result = mysqli_query($con,$sql);
$sql = "SHOW TABLES LIKE '".$table."'"; // requires: ' ' or fails
$result = mysqli_query($con,$sql);
Can someone explain why?
EDIT: I guess the essence of my question is that: Both functions worked fine without any kind of quotes with mysql_query, and both failed mysqli_query without some kind of quotes. Meaning I will have to fiddle around with half my query's when changing from mysql_ to mysqli_
In your first select statement you are trying to select a table by it's name, hence it will accept the name either with ` or without them, but now with single or double quotes. These should work :
$sql = "SELECT * FROM `table_name`";
$sql = "SELECT * FROM table_name";
In the second case you need to pass in a string to be compared by the like statement hence you need to surround it either with single ' or double " quotes:
$sql = "SHOW TABLES LIKE 'string'";
$sql = "SHOW TABLES LIKE \"string\"";
Edit:
Check out this previous answer on SO as well:
Using backticks around field names
Edit 2:
Since we (me and in comments) suggested that backticks are somehow optional, keep in mind that as a best practise use them whenever you can since although it will allow you to pass most queries without them, some queries using MySql reserved words would break when containing mysql reserved words
First of all, I know it's not how it's supposed to be. But the system has been setup like this so I have to try and work with it.
I have a column of entries in a mySQL table that look like this {12}-{32} and so forth. 12 is the id of the brand of a car, 32 the model.
Now I have to create a query in PHP where a part of it is like this:
(PD1.fieldValue = '{". $_SESSION['carId'] ."}-{". $_SESSION['carModelId'] ."}'
Guess what, that doesnt work with curly braces ofcourse. The SESSION part is completely empty (yes, they have a value outside the query).
Is there anyway to fix this so I still can send the variables inside the braces to mySQL?
Whenever you find yourself having trouble getting some characters into your database, that is a strong hint that your database code is insecure and vulnerable to SQL injection. You have to take a step back and look a little more broadly, thinking "What are all of the possible characters that aren't being escaped properly?" Luckily, you don't have to actually know. You just need to use the built-in escape functions.
The ideal solution is to use placeholders. The syntax depends on what database API you're using (mysqli, or PDO; deprecated mysql doesn't support them). There exist many excellent resources on how to use placeholders; this is the first result I pulled from Google and it looks right to me.
The somewhat less ideal solution is to use the real_escape_string function for your database API. Example for either mysqli or mysql:
// Using heredoc syntax, you can clean up your queries like so.
$sql_template = <<<SQL
SELECT
PC.id AS cId,
P.id AS pId
FROM PAGE_CATALOG P
LEFT JOIN PAGE_CATALOG_CONFIG PC ON (PC.id = P.cId)
WHERE PD1.fieldValue = '%s'
AND P.productCode REGEXP '%s'
AND PC.id = '1'
AND P.enabled = '1'
GROUP BY P.id
ORDER BY P.productVolgorde ASC
LIMIT 0, 10
SQL;
// For mysqli:
// $mysqli = new mysqli(...)
$sql = sprintf(
$sql_template,
$mysqli->real_escape_string('{' . $_SESSION['carId'] . '}-{' . $_SESSION['carModelId'] . '}'),
$mysqli->real_escape_string($MAL_TYPE)
);
$result = $mysqli->query($sql);
// For mysql:
$sql = sprintf(
$sql_template,
mysql_real_escape_string('{' . $_SESSION['carId'] . '}-{' . $_SESSION['carModelId'] . '}'),
mysql_real_escape_string($MAL_TYPE)
);
$result = mysql_query($sql);
This question already has answers here:
How do I create a PDO parameterized query with a LIKE statement?
(9 answers)
Closed 3 years ago.
I am new to PHP, and am trying to learn to use PDO to connect to a test MySQL db. I have the following:
try {
$db = new PDO('mysql:dbname=MYDBNAME;host=MYHOST', 'USERNAME', 'PASSWORD');
$query = "select * from books where ? like '%?%'";
$stmt = $db->prepare($query);
$stmt->execute(array($searchtype, $searchterm));
} catch(PDOException $e) {
echo 'PDOException: ' . $e->getMessage();
}
When I try it I get the following warning:
Warning: PDOStatement::execute() [pdostatement.execute]: SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens
When I remove the like clause, and the $searchterm param, it returns the result properly. I thought -- like '%?%' -- might not be a legal way to create this query under double quotes, so I tried escaping ', which did not work. I looked around for a solution, and found that someone moved '% and %' down to where $searchterm is:
$query = "select * from books where ? like ?";
...
$stmt->execute(array($searchtype, '\'%'.$searchterm.'%\''));
I got the same result.
Any help is appreciated. Thanks!
/ UPDATE ****/
I found on example 12 of http://us3.php.net/manual/en/pdo.prepared-statements.php
Example #12 Invalid use of placeholder
<?php
$stmt = $dbh->prepare("SELECT * FROM REGISTRY where name LIKE '%?%'");
$stmt->execute(array($_GET['name']));
// Below is What they suggest is the correct way.
// placeholder must be used in the place of the whole value
$stmt = $dbh->prepare("SELECT * FROM REGISTRY where name LIKE ?");
$stmt->execute(array("%$_GET[name]%"));
?>
I tried this, and even though I no longer get a Warning, I do not get any results. However when I execute the query directly I will get a couple of results. Any thoughts?
Don't add the quotes when binding prepared variables and dont bind the column name
$query = sprintf( "select * from books where %s like ?", $searchtype );
...
$stmt->execute(array($searchtype, '%'.$searchterm.'%'));
$stmt->execute(array($searchtype, '\'%'.$searchterm.'%\''));
This isn't how parameterised queries work. Inserted parameters act as literal strings already, you don't have to add quote delimiters around them or escape them (that's the whole point), and if you try, you're literally comparing against the string single-quote-searchterm-single-quote.
Consequently if you are (as I suspect) intending to compare a particular column against a literal string, you don't parameterise the column name. At the moment you are comparing a literal string to another literal string, so it'll either always be true or always false regardless of the data in the row!
So I think what you probably mean is:
$query= "SELECT * FROM books WHERE $searchtype LIKE ?";
$like= "%$searchterm%";
$stmt->execute(array($like));
thought naturally you will have to be very careful that $searchtype is known-good to avoid SQL-injection. Typically you would compare it against a list of acceptable column names before using it.
(Aside: there is a way of putting arbitrary strings in a schema name that you can use for a column, but it's annoying, varies across databases and there isn't a standard escaping function for it. In MySQL, you backslash-escape the backquote character, quotes and backslashes and surround the name with backquotes. In ANSI SQL you use double-quotes with doubled-double-quotes inside. In SQL Server you use square brackets. However in reality you vary rarely need to do any of this because really you only ever want to allow a few predefined column names.)
(Another aside: if you want to be able to allow $searchterm values with literal percents, underlines or backslashes in—so users can search for “100%” without matching any string with 100 in—you have to use an explicit escape character, which is a bit tedious:)
$query= "SELECT * FROM books WHERE $searchtype LIKE ? ESCAPE '+'";
$like= str_replace(array('+', '%', '_'), array('++', '+%', '+_'), $searchterm);
$stmt->execute(array("%$like%"));
The problem I see is if you had written a wrapper for PDO, then you would have to somehow handle this separately. The answer I had found and loved was write your query and concat the % to the parameter. i.e. "WHERE column like concat('%', :something, '%')"
I have a code below:
<?php
require "institution.php"
/* in this portion, query for database connection is executed, and */
$institution= $_POST['institutionname'];
$sCampID = 'SELECT ins_id FROM institution where ins_name= '$institution' ';
$qcampID = pg_query($sCampID) or die("Error in query: $query." . pg_last_error($connection));
/* this portion outputs the ins_id */
?>
My database before has no mixed-case table names, that's why when I run this query, it shows no error at all. But because I've changed my database for some reasons, and it contains now mixed-case table names, i have to change the code above into this one:
$sCampID = 'SELECT ins_id FROM "Institution" where ins_name= '$institution' ';
where the Institution has to be double quoted. The query returned parse error.
When i removed this portion: where ins_name= '$institution', no error occured.
My question is how do I solve this problem where the table name which contains a mixed-case letter and a value stored in a variable ($institution in this case) will be combined in a single select statement?
Your answers and suggestions will be very much appreciated.
You can use the double quote instead
$sCampID = "SELECT ins_id FROM \"Institution\" where ins_name= '$institution'";
<?php
require "institution.php"
/* in this portion, query for database connection is executed, and */
$institution= pg_escape_string($_POST['institutionname']);
$sQuery = "SELECT ins_id FROM \"Institution\" where ins_name= '$institution'";
$qcampID = pg_query($sQuery)
or trigger_error("Error in query: $sQuery." . pg_last_error($connection));
/* this portion outputs the ins_id */
?>
Note
pg_escape_string as it ought to be used, not to protect from any injections but as just a part of the syntax.
trigger_error which should be used instead of echo (and note proper variable name)
and double quotes or your variable won't be extrapolated ( http://php.net/types.string for ref)
and slashes at double quotes (same ref)
$sCampID = 'SELECT ins_id FROM "Institution" where ins_name= \''.$institution.'\'';
String escaping.
As another commenter posted, read about SQL injection. What I have is not injection safe, consider using something with prepared statements, preferably PDO.
To add to other answers (quote the table name, and use prepared statements to gain security and performance), read about PG and tables case sensitivity. If you have the option, you might consider to change your db schema, so that tables names (and columns and identifiers in general) are all lowercase. That would simplify a little your queries - (but require you to check all your actual quoted queries and unquote them).
What happens if $institution contains the following string: ' or 1 = 1; --
That's what we call an SQL injection attack, and it's a super-easy way for hackers to steal your data -- and get you into big trouble with your customers.
You need to escape that string using pg_escape_string() before putting it into an SQL query. I like to use sprintf() to build my queries:
$sql = sprintf("SELECT ins_id FROM \"Institution\" where ins_name= '%s'", pg_escape_string($conn, $institution));
In the above example, $conn is the connection identifier, created by calling pg_connect().