I'll jump straight into it. Using php I'm having a problem deleting a record from the database if i use a variable as the value. The line of code below works perfectly
mysqli_query($con,"DELETE FROM highScores WHERE Name='David'");
But the name of the user will change, therefore I need to declare it as a variable. I've tried all kinds of variations but nothing seems to work. My latest failed attempt was the code below, which is the way i declare a varible when i'm inserting.
mysqli_query($con,"DELETE FROM highScores WHERE Name='{$name}'");
In situations like this it is good to check that variables actually contain something you expect it to. And I find also that echoing entire query strings is a good way to find out why a query isn''t working.
$sqlquery = "DELETE FROM highScores WHERE Name='{$name}'";
// have a look at the query...
echo "<pre>$sqlquery</pre>";
// use it...
mysqli_query($conn,$sqlquery);
I should warn you that if $name comes from somewhere untrusted, such as a publicly viewable html form, then it needs to be made 'safe' before using it in a query. Look into 'prepared statements'. Once you know your code is correctly populating your variable, make sure it is made safe before putting it in your query.
I'm not sure if..
{$variable} is valid in a query.
The way I insert a variable into a query, is called concentration.
mysqli_query($con,"DELETE FROM highScores WHERE Name='" . $name . "'");
The period adds 2 strings together.
However, what you're trying to do is vulnerable to SQL injection. If I were you, I'd be careful on what could be inside $name.
EDIT: My mistake, I'm used to a class that inserts the quotes for me.
Try this to get it running:
mysqli_query($con,"DELETE FROM highScores WHERE Name='".$name."'");
Make sure $name is a proper formed string like string(5) David, otherwise it might not lead to the desired results or may even break your query completely. You can make sure of this if you put a mysqli_real_escape_string like this
$name = mysqli_real_escape_string($con,$name);
before you execute the query
I landed here while searching for solutions to the same problem, but just discovered my database user didn't have delete privileges. I had earlier removed this privilege for security reasons.
Related
This is something I have been trying to figure out for a bit, it is the most simplest of queries that does not seem to want to work for me (only in php mysqli, works in console sql)
First I am using a prepared statement, merely looking for a match on a specialized id (from another service) to update the relation to use my primary key for easier searching on my end.
The query is as follows:
$query = "SELECT id
FROM {$this->config->dbprefix}{$table}
WHERE sf_id = ?
LIMIT 1";
I use this as one line, I split it up for better readability here
I then check that the prepare statement is valid (I do this in multiple places and it works everywhere else.
if(!($ret = $this->dbo->prepare($query))){
//handle error, this part is never called
}else{
//everything is fine, code in here is below
}
Up to here everything seems fine. Checking table and prefix manually shows they are working and referencing the proper table.
$ret->bind_param('s',$id);
$ret->execute();
$ret->bind_result($retId);
$ret->fetch();
$count = $ret->num_rows;
The problem is here, the query always returns 0 for the num_rows. Checking the query manually and trying it in console returns 1 result as it should. So far with it being such a simple query I just cannot wrap my head around why it would work elsewhere, but not here. I am sure this is the proper way to build it (I have many other queries structured similar).
Is there any kind of confusion I may be experiencing? Something easy to miss that could cause a query like this to not return results?
EDIT:
I have attempted further error handling, and trying an if test on execute does not trigger an error, though I will try more.
To expand I have a raw output of the $query variable and the id variable. By combining them and manually attempting the query in console I get the proper result. My thoughts are on somehow the prepare statement is escaping, causing the string variable $id to not properly match. Though that is just speculation.
You need to call store_result() before trying to access num_rows. Without it, the statement handle does not know how many rows are in the result set.
$ret->bind_param('s',$id);
$ret->execute();
$ret->bind_result($retId);
$ret->store_result();
$count = $ret->num_rows;
// perhaps add error handling based on number of rows here
$ret->fetch();
I would like to be nice to my users but don't want to get malicious code by mistake.
Looking in SO many questions I decided to go whitelisting, so I get only characters I approve.
How is it possible to be kind to the user, so I let them enter many characters and still keep my inputs safe from malicious code?
I am using Apache with PHP 5.3.8, I haven't incorporated PDO because the time I heard of it it I was deep into the project and feared it might be too big of a change.
Any ideas would help!
If it can be output to a user, you must prevent the potentially malicious user from including HTML tags in his code. For example, if, in that post, I could include a script tag, that could be very dangerous for any user reading my post. To prevent this, you want to use htmlentities:
$clean_data = htmlentities($_POST['data']);
That way, my <script> tag will be translated as <script> so it won't harm users when displayed by their browsers.
Now, if you want to save my post in your database, you must beware of SQL injections. Let's say you're saving my post with that query (yes, you shouldn't use mysql_* functions as they are deprecated, but that's just to explain the idea) :
mysql_query($db, "INSERT INTO posts(data) values('$clean_data');");
Sounds good ? Well, if I'm nasty, I'll try to include that post :
test'); DELETE FROM posts; SELECT * FROM posts WHERE data = '
What your MySQL gets is then
INSERT INTO posts(data) values('test'); DELETE FROM posts; SELECT * FROM posts WHERE data = '');
Ouch. So, you must basically prevent your user from including quotes and double quotes in his post, or, more precisely, you should escape them. That really depends on the library you are using, but in the obsolete one I used, that would be written :
$really_clean_data = mysql_real_escape_string($db, $clean_data);
mysql_query($db, "INSERT INTO posts(data) values('$really_clean_data');");
So, with the above malicious post, MySQL would now receive
INSERT INTO posts(data) values('test\'); DELETE FROM posts; SELECT * FROM posts WHERE data = \'');
Now, to MySQL, the whole INSERT INTO posts(data) values('test'); DELETE FROM posts; SELECT * FROM posts WHERE data = ''); part is a correct string, so what happens is what you want to happen.
Basically, that's all you need in almost all the cases. Just remember that, when you feed user data to an interpreter (it can be a web browser, a SQL engine or many other things), you should clean that data, and the best way to do it is to use the dedicated functions that should come with the library you are using.
Just to add to the answer that Fabien already gave, text data types are not the only item you need to be concerned with. Numbers are just as important. Type casting your variables is one way to handle that. For example,
$really_clean_data = mysql_real_escape_string($db, $clean_data);
$query = "UPDATE posts SET post = '".$really_clean_data."' WHERE id = '".(int)$_POST['id']."'";
All data submitted, including the id number of the post you'll be looking to update, is just as suspect and just as open to malicious fiddling as a textarea or text input entry. When you know it should be an integer (number) you can cast it as such. If it's not numeric, that (int) will cast it as 0. You can't update row 0 so the SQL query will fail.
To check for that failure prior to executing the query, you can check the posted data to see if it is a number using the is_numeric() function.
if(!is_numeric($_POST['id'])){
die("Post id is not a number.");
}
For input fields, most notably username and password fields, you can set a max length and check. For example,
if(strlen($_POST['username']) > 24){
$error = "username is too long";
}
If you can get creative about it, preventing SQl injection is actually fun! Keep in mind that a year from now everything on this page could be completely outdated and irrelevant. Security is a process, not a step, so keep on top of it.
I've been coding with PHP and MySQL for about a year now and have gotten the hang of it pretty well; constructing really complicated queries with joins and calculated fields and all the other joys of MySQL hasn't been a problem for me in months.
BUT there's something syntactically screwy with the following chunk of code that I can't figure out - even though it's impossibly simple, and, even more infuriating, is closely related to other parts of the project that I'm working on (and which works flawlessly).
Here's the problem code I'm trying to run, followed by the bugchecking I've already done to try to isolate the problem.
If anyone has any suggestions, I'd be totally grateful because I'm beginning to lose my mind.
Problem:
I'm really losing my mind over this, so please don't laugh when you see the code:
$query="SELECT count(somefield) FROM db_name WHERE otherfield='".$myvariable."'";
My query finds no results when using a certain variable as part of a field search - even though I know that there are over 900 records in the database that should match.
Bugchecking:
Because I know the value of the variable I'm passing to the query, I've tried hardcoding it into the query and it works fine.
I've run the query in the MySQL console (again, of course, hardcoded instead of with the variable) and it works fine.
To my mind, these two facts eliminate the possibility that there's something syntactically incorrect with the PHP version of the query.
In order to eliminate all possible database connection issues and to make sure the problem isn't related to iterating through the results returned, instead of trying to get the actual results, I've altered my original query to return only the count of the results and have incorporated the standard or die(mysql_error()) statements during the connection sequence. The query is executing, but is finding 0 results, so that eliminates the possibility that it's a connection issue.
I've verified that the field I'm checking is the correct field for the information I'm looking for (like I said, it runs fine if I hardcode the variable into the query... which, of course, will not be an option in the finished code).
I've checked the type of the variable before trying to pass it into the query (figuring that maybe, because it's pulled from a returned xml earlier in the script, that maybe it was showing up as an array or something). It typed as string.
I've verified that the variable is formatted in the way that I expect it to be found in the database; strtoupper, etc.
I've tried using LIKE '%".$myvariable."'"; still no dice.
Anyone have any suggestions for what I can do to figure out what the hell is going wrong? Thanks so much!
It's not a PHP issue so quotes have nothing to do with it.
The query has no error, so you'll need to debug it step by step.
I. SELECT count(*) FROM table_name
II. SELECT count(*) FROM table_name WHERE field='$myvariable'
Where you're dealing with PHP variables in query, echo the query and run it directly in database to omit PHP's side of error.
III. SELECT count(somefield) FROM table_name WHERE field='$myvariable'
Is the $myVariable escaped? If not, escape it using
$escapedVariable=mysql_real_escape_string($myVariable);
and then run
$query="SELECT count(somefield) FROM db_name WHERE otherfield='$escapedVariable'";
Thanks so much to everyone who tried to help, but I figured it out several hours after posting: The first problem was that I forgot to use mysql_real_escape_string($myvariable)... the reasons for how and why I forgot are manifold, but there it is.
So, after plugging that guy back in (which I had ASSUMED had been in this particular module of my code in the first place, but that's where "assuming" gets you, lol), I thought I had the whole thing licked. Three hours later, and still nothing. THEN I realized that it had to be related to XML that was being parsed into the $myvariable... so around and around we went with that one for a few more hours.
FINALLY, I realized that the real culprit was my eyes (which aren't so great).. what looked like a perfectly legit quoted string while reading a debug echo of the query before running turned out to have leading and trailing white space (which, of course, I instantly removed with $myvariable=trim($myvariable, " "), and, that, of course, solved the entire problem...:<
... Yes, I am an idiot, and I'm sorry, but, after working over this UTTERLY INFURIATINGLY stupid line of code for over 48 hours (I'm used to writing things like:
$query="UPDATE db_one.table_one SET item1='".(string)$result_array[$i][1]."', item2='".(string)$result_array[$i][2]."' WHERE thing3=".(string)$result_array[$i][19];
... and other assorted fun nonsense), I had to resort to asking (because I - no pun intended - couldn't "see" the problem... ugh)... SO... I am an idiot, and I'm sorry (but encouraged by the efforts of all of you nice people who tried to help) and am sorry for wasting everyone's time. I need to learn how to handle XML much *more*.
Sorry and thanks again!
I always wrote it like this
$query="SELECT count(somefield) FROM db_name WHERE otherfield='$myvariable' ";
Try removing the double quotes and dot at the variable name
You shouldn't need the parenthesis around the var. Plus look at other changes.
$query="SELECT count(*) FROM table_name WHERE field='$myvariable'";
I have written a PHP OO class which will update 4 fields of a certain row in a table. For now the row is decided by a constant (user with name 'jip')
I have corrected the query in a previous post here, so i'm pretty sure the query itself is fine. So, there must be some sort of error within the class itself. Probaply the vars don't reach the query somehow. I have been looking for hours, but can't find the problem. I have linked both files of the class, since i downt know where the error is, the values just don't show up in the database. If anyone would like to check them, (s)he'd make my entire week! SO here is the link and i hope someone is willing to help :)
UpdateForm.php: http://pastebin.com/dUaZPrn6
Update.class.php: http://pastebin.com/6mnL4DzE
Try replacing mysqli_real_escape_string($conn, $variable) with
$conn->real_escape_string($variable);
For example,
$conn->real_escape_string($this->Lengte_update);
You're using the object-oriented style, so you can't use the procedural escape function. See the docs on mysqli::real_escape_string.
Edit:
The query isn't being executed. You assign the query to $query, but you need to call
$conn->query($query);
For anything to happen in the database.
So, I almost have my delete function working, I have the page loading correctly without any fatal errors but it's still not doing the trick.
Here is the portion of my while loop:
echo "<a href='http://www.###$#%##%#.org/Profile.php?id=".$prof->id."'>";
echo " delete";
echo "</a>";
And here's the portion of my query which is obviously wrong:
$query = "UPDATE `ProfileComments` SET `status` = 'dead' WHERE `id` = '".$prof->id."' LIMIT 1";
So, how do I get this to delete the comment on the page? And mark the status dead in the database?
From your sql it looks like you are doing a soft delete, which is fine. Your select statement needs to exclude comments that have a status of 'dead'
SELECT columns FROM ProfileComments WHERE status != 'dead' AND id = {$prof->id}
Of course that's a guess without seeing how you populate prof->id when you generate the link.
There's a couple of other problems with your post though:
As others have suggested, you should use parameterized queries otherwise you leave yourself open to sql injections
You shouldn't be doing the delete via a get request (using a naked anchor). Either do the delete using AJAX or via a form. Modifying server data via a get is a bad practice.
Just because you're not seeing fatal errors, your code doesn't have to behave like you want it to.
Examine the content of $prof->id by, inside of the loop, putting it through var_dump and then die, this will let you control what the property holds at the moment you want to print it out.
The same thing applies in your query, var_dump to see what it contains.
Not seeing more of your code (and not knowing your experience level), I'm not sure where you actually need help, so forgive me if my question/advice is obvious and too basic for you:
How is $prof->id getting populated in Profile.php? Are you pulling it off of the request (like so: $id = $_REQUEST["id"])?
And as Michael said, do please use parameterized queries. (If you don't care about children, at least think of the kittens!)
Your SQL statement looks fine, and the html code is fine too. To locate the problem
You need to make sure your SQL is getting the right parameter, the id in this case. just echo it out, if the id is missing or wrong you know $prof->id needs fixing.
also check the link dumped by your php, again does it contain the right id?
Make sure you don't have any errors before you execute the SQL, basically make sure that SQL query statement is called. and make sure your db connection is live.
When mysql statement is wrong it won't throw a fatal error, you need to print the error yourself by mysql_error().