This question already has answers here:
How to include a PHP variable inside a MySQL statement
(5 answers)
Closed 1 year ago.
I have a problem with my php code when i try to choose a string in my database.
Well, I have a table "news" and a field "category" (TINYTEXT type) there. And I try to display a string from this table by using "where clause":
$Sql = 'SELECT * FROM `news` WHERE `category` = '.$Param['category'].' ORDER BY `id` DESC';
I must say that I received "$Param['category']" by using URL Path: 1
So, if my "category" value of any string in table has any string type value like "games" 2, 3 - string from my table isn't displayed with this error "Fatal error: Uncaught mysqli_sql_exception: Unknown column 'games' in 'where clause'"
But, if I change the "category" value of string in the database into anything numeral value - the string from my table is displayed correctly!4, 5
What's wrong with my code? Thank you in advance! Sorry for the mistakes.
You need to use prepared queries, both for the sake of SQL injection protection, and because it will fix your bug. I believe the issue is that you don't have any quotes at all around your parameters. As a result you're building queries like this:
SELECT * FROM `news` WHERE `category` = games ORDER BY `id` DESC
SELECT * FROM `news` WHERE `category` = 1 ORDER BY `id` DESC
The latter is a valid query: mysql looks for records where the category is 1. The former is not: the query tries to find records where the column category matches the column games. The latter doesn't exist so you get an error. You want to build these queries:
SELECT * FROM `news` WHERE `category` = 'games' ORDER BY `id` DESC
SELECT * FROM `news` WHERE `category` = '1' ORDER BY `id` DESC
Which you would do with this code:
$Sql = "SELECT * FROM `news` WHERE `category` = '".$Param['category']."' ORDER BY `id` DESC";
(note that I switched to double quotes and included single quotes around the input parameter). BUT THIS IS STILL WRONG as it leaves you extremely vulnerable to SQL Injection, which would allow an attacker to potentially download or modify your entire database. Take the time to read up and learn how to use prepared queries, which is both more secure and also would have prevented this bug in the first place.
Others have suggested you use parameterized queries. That's good advice, but they didn't show you what it looks like (not that it's hard to find examples).
Here's a quick example using PDO:
$Sql = 'SELECT * FROM `news` WHERE `category` = ? ORDER BY `id` DESC';
$stmt = $pdo->prepare($Sql);
$stmt->execute([ $Param['category' ]);
This executes the query as if you had put $Param['category'] into the SQL, but it does it completely safely, even if the value contains special characters.
You don't put quotes around the ? placeholder. It's implied that the query will treat it as a single scalar value, not a column name. In fact, you can use parameters only for values — not for column names, or expressions, or SQL keywords or anything else.
Writing code using query parameters is easier than not using parameters, because it makes your code easier to write and easier to read.
You have to put quotes around any string in the query if it is not a field in the table. Try this:
$Sql = "SELECT * FROM `news` WHERE `category` = '".$Param['category']."' ORDER BY `id` DESC";
As was mentioned if you are pulling in that string from a source where you have to word about code injection you should use prepared statements or PDO.
Related
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 9 years ago.
Improve this question
I want to display certain data from tableA in the database, but only the ones which have similar location as the user from tableB, who is logged in.
I am using the code below, but I get the following error: Unknown column 'Amsterdam' in 'where clause'.
The code I am using is:
$query = 'SELECT * FROM tableA WHERE `city` LIKE '.$user['city'].' ORDER BY `id` DESC';
$result = mysql_query($query, $conn) or die(mysql_error());
$row_result = mysql_fetch_assoc($result);
echo $row_result['name'];
What do you think might be the error?
You need to concatenate the value of $user['city'] with single quotation marks.
Assuming the city is Amsterdam, what you are aiming for is a SQL statement that reads:
SELECT * FROM tableA WHERE `city` LIKE 'Amsterdam' ORDER BY `id` DESC
but what you are generating is:
SELECT * FROM tableA WHERE `city` LIKE Amsterdam ORDER BY `id` DESC
so MySQL is treating the name of the city as a table column, because it is not enclosed.
Your code needs to be:
$query = "SELECT * FROM tableA WHERE `city` LIKE '".$user['city']."' ORDER BY `id` DESC";
$result = mysql_query($query, $conn) or die(mysql_error());
$row_result = mysql_fetch_assoc($result);
echo $row_result['name'];
The above example used double-quotes to enclose the static text, but you can use single-quotes by escaping the ones that need to form the string value:
$query = 'SELECT * FROM tableA WHERE `city` LIKE \''.$user['city'].'\' ORDER BY `id` DESC';
city is a text field. Therefore the SQL parser expects text, which has to be in quotes.
"'.$user['city'].'"
You may want to put additional quotes around $user['city'] as below:
$query = 'SELECT * FROM tableA WHERE `city` LIKE `'.$user['city'].'` ORDER BY `id` DESC';
As others have noted, you're missing the quote marks around $user['city']
Aside from that, can I recommend that you stop using the mysql_ functions as they've been deprecated.
If you move to mysqli_ or PDO:: calls, you open up the possibility of using prepared statements which will make life a lot easier and may actually give you cause to think "How did I ever cope without these?"
I am not sure if I am apporaching this in the best way, but what I am trying to do is use two php variables for a IN clause in a mysql select query.
"select * from `user` where '$phpvar1' IN ('$phpvar2')"
Normally instead of $phpvar1 I would use a column name in the user table and it works fine, however in my case now I need the $phpvar1 variable to be used as a temporary column in this specific select query. Since $phpvar1 is dynamic in each situation, I do not want to store it. What can I do? Thanks!
EDIT: To clarify, $phpvar1 is not a column in the table, but I want it to act as one only for this one query. In this query I want $phpvar1 which is equal to for example: "cat", where as "cat" is the data that would be found in the column, and then this data ("cat") would be used in the IN clause to see if $phpvar2 contains "cat"
Basically what I want it to do is this:
SELECT * from `users` where 'mouse' IN ('cat', 'dog') and `userID` = '1'
the rows returned should have a userID = 1 AND meet the IN clause, since 'mouse' is not in ('cat,'dog') there won't be any rows returned in this case.
Rewrite your query to:
"SELECT * FROM `users` WHERE '$phpvar1' IN ('".implode("', '", $phpvar2)."') and `userID` = '1'"
Assuming that $phpvar2 is array containing values to check for.
Try
$sql = "select * from `user` where ".$phpvar1." in (".$phpvar2.")";
Your php variable should be in the select part
Select $phpvar,otherstuff, from user where x in ('$phpvar2');
I am pulling a column in an existing script into my template files, and everything is working great.
The only problem is, that this script has a column called order, and every row then has a number in that column to show which should be at the top etc. If I set my query to "ORDER BY name" for example, everything works fine, but when I use "ORDER BY order", then I get a SQL error.
Can I not have a column called order? I can't change column name, because it's part of the script.
Is there a way around it?
This is the line in my SQL query:
SELECT * FROM categories WHERE hide = 0 ORDER BY order
order is a keyword in SQL. So if you wish to use a keyword as a name, use backtick characters around it:
SELECT * FROM categories WHERE hide = 0 ORDER BY `order`
Try that :)
If you are working with Postgres just use "column_name", e.g:
SELECT "order" FROM table_name WHERE "order" > 10 ORDER BY "order";
AS orderis a SQL keyword, you should escape it properly as an field identifier by using backticks:
SELECT ... FROM ... ORDER by `order`
Try using backticks:
SELECT * FROM `categories` WHERE `hide` = 0 ORDER BY `order`
ORDER is a reserved word in SQL. You can use a reserved word as a column name but you must surround it in backticks when referencing it. It's good practice to surround all your column names in backticks so you don't run into this issue.
Try using back ticks around the column name, that should do it.
From the manual:
A reserved word can be used as an identifier if you quote it.
So you can use it like this:
SELECT * FROM categories WHERE hide = 0 ORDER BY `order`
Worked for me with brackets. SELECT T.* FROM dbo.test AS T ORDER BY [T].[ORDER]
This question already has answers here:
How can I prevent SQL injection in PHP?
(27 answers)
Closed 2 years ago.
The sql injection will work only when my query looks like below sample
SELECT * FROM login WHERE id = $my_id_va;
Assume if my query is
SELECT * FROM login WHERE id = $my_id_va ORDER BY id DESC
Than I will get following error
#1064 - 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 'order by id desc' at line 1
So, this 1 or 1=1; SHOW TABLES will not work, correct?
My site was hacked successively many times.
I want one quick answer: When my query looks like the following one, what ways or which types of query can they use to hack my site?
SELECT * FROM login WHERE id = $my_id_va ORDER BY id DESC
What are the ways to execute the show table in the following query
SELECT * FROM login WHERE id = $my_id_va ORDER BY id DESC
I am also using escaping function to handle the query string values, like mysql_real_escape_string($my_id_va). Yes, obviously this for single related hack, but not sure.
Added some more
SELECT EventActuallyCharged, EventDate FROM tblevent WHERE EventDate between '2011-07-21 or 1=1; SHOW TABLES --' and '2011-07-31' ORDER BY EventDate DESC
but show table not worked
If you are using PHP5, use parametarized query, use PDO.
Int cast
If id is a number, you can int-cast your variable as well. Integers are safe to use:
$x = (int)$yourInputVar;
$s = "select * from Table where id = $x";
mysql_real_escape_string
If you want to pass a string, you can, and should, use mysql_real_escape_string, but this function escapes only those characters that are inside the string. You will still need to add quotes around the string, so:
$x = mysql_real_escape_string('hello');
$s = "select * from Table where id = $x";
.. will result in the query: select * from Table where id = hello. This is obiously not a valid query, since hello should be in quotes.
Change the query to:
$x = mysql_real_escape_string('hello');
$s = "select * from Table where id = '$x'";
.. and everything works fine. You add the quotes around, and mysql_real_escape_string takes care of special characters inside the string, if any.
Parameters
Another solution is to use parameterized queries. This can by done using MySQLi or PDO. The advantage is that you only tell your database where a variable should be inserted, and the database takes care of the escaping yourself.
It also may add a performance benefit, because these queries could be cached without their parameters, make a more efficient use of the query cache. This doesn't really work yet in current versions of MySQL, though.
You are right that 1 or 1=1; SHOW TABLES will give a syntax error but this will work:
1 or 1=1 --
The -- comments out the rest of the query.
In your case the value is an integer so instead of using mysql_real_escape_string you can use intval.
If you set $my_id_va to:
1 or 1=1; SHOW TABLES --
The -- will comment out the rest of the command, effectively terminating it.
I'm not sure what effect mysql_real_escape_string will have on the query. What you should be doing is parameterized queries.
1. First query somehow secured
$sql = sprintf('SELECT * FROM login WHERE id = %d ORDER BY id DESC', mysql_real_escape_string($my_id_va));
2. Second query somehow secured
$sql = sprintf("SELECT EventActuallyCharged, EventDate FROM tblevent WHERE EventDate BETWEEN '%s' AND '%s' ORDER BY EventDate DESC",
mysql_real_escape_string($start_date),
mysql_real_escape_string($end_date));
Read the docs about sprintf if you don't understand it.
However, as others have said, it would be very very secure if you would use parameterized queries with a class such as PDO or MySQLi.
Im trying to get this query to work but i get this error:
Unknown column 'zips.city' in 'having clause'
`$query = "SELECT
zips.*
FROM
zips
HAVING
zips.city LIKE '%$city%'
AND
zips.stateabbr LIKE '%$state%'
LIMIT 1";
$result = mysql_query($query) or die (mysql_error());`
my zips table has a city column, so im not sure what the problem is, i know im accessing the database because i can run this query with no errors:
$zip1query = "SELECT
zips.*
FROM
zips
WHERE
zips.zip = '$zip'
";
any advice would be much appreciated! thanks!
The having clause doesn't mean the same thing as the where clause : when running a simple query, you should use where -- which is what you did in your second query, that works.
having is used when the condition has to be applied on the result of a group by clause.
Which means that, here, your query should be build this way :
$query = "SELECT zips.*
FROM zips
where zips.city LIKE '%$city%'
AND zips.stateabbr LIKE '%$state%'
LIMIT 1";
With that, if you still have an error about a non-existing or not-found column (at least for city and/or stateabbr), it'll be because that column doesn't exist in your table.
In this case, there is not much we can do : you'll have to check the structure of your table, to determine which columns it contains.
You can check that structure using a web-based tool like phpMyAdmin, or using an SQL instruction such as :
desc zips;
For reference, quoting MySQL's manual page for select :
The SQL standard requires that HAVING
must reference only columns in the
GROUP BY clause or columns used in
aggregate functions. ...
Do not use HAVING for items that
should be in the WHERE clause.
For example, do not write the
following:
SELECT col_name FROM tbl_name HAVING col_name > 0;
Write this instead:
SELECT col_name FROM tbl_name WHERE col_name > 0;
...
The HAVING clause can refer to
aggregate functions, which the WHERE
clause cannot
Try using WHERE instead of HAVING.
The proper way to do it is by using a WHERE clause.
$query = "SELECT
zips.*
FROM
zips
WHERE
zips.city LIKE '%$city%'
AND
zips.stateabbr LIKE '%$state%'
LIMIT 1";
HAVING is to be used when you are GROUPing, see here for an explanation
o jeez sorry guys i figured out the problem, apparently i put a space before city when i named the columns in my table. so i renamed the column and it works thanks anyway chaps! but using the where function instead of having must speed things up alot, thanks guys!