PHP/SQL never updates only inserts - php

For some reason my insert/update check only ever inserts. the value userID does have a value so i dont know what is up with this. Any ideas?
$result = mysql_query("SELECT * FROM users where userID = $userID ");
if (mysql_num_rows($result) > 0) {
mysql_query("UPDATE users SET firstName='$firstName', lastName='$lastName',
birthday='$birthday', update='$today', accessToken='$accessToken', emailOne='$emailOne' WHERE userID='$userId'");
} else {
mysql_query("INSERT INTO users (userID, firstName, lastName, birthday, updated, accessToken, emailOne )
VALUES ('$userId', '$firstName', '$lastName','$birthday', '$today', '$accessToken', '$emailOne')");
}

You'd be far better off doing INSERT ... ON DUPLICATE KEY UPDATE. Your version is subject to race conditions. It's entirely possible that between the time you do the SELECT * and then attempt the update/insert queries, ANOTHER script has already inserted the same ID number and then your script breaks. This also reduces the database load by one query.
As well, unless you've passed all those variables in the query through mysql_real_escape_string(), you'll probably be getting a visit from Little Bobby Tables.

From the way you're inserting the records, it seems that your userId field is a varchar (or alphanumeric) field. So your query NEVER reads the data that matches it since it is searching for it as a numeric. You've got to re-write the first line as:
$result = mysql_query("SELECT * FROM users where userID = '$userID' ");
Hope it helps.

Related

Selecting a row where date=NOW()?

I am trying to create a table that logs steps depending on date and the user id. But when I run my code, it happens that I get duplicate rows if a user logs their steps several times a day. I can't have a date with a unique key because that would cause all other users unable to log steps if a any other user has logged steps the same day. So my point is that I want to remove the option of having duplicate rows where user id and date is identical. I have two tables
Table a and table b, and I will refer to them as something.a and something.b
I have a problem with returning a valid row when using $entry = "SELECT * FROM table.a WHERE userid.a = '$user_id.b' AND date=NOW()"
I want to use it as a conditional to decide to either UPDATE or INSERT INTO table.a. I have user_id.b from an previous query which works as it is, so I will leave that as it is for now.
Here is how I query the database:
$entry_result = mysqli_query($conn, $entry);
Which is used here:
if (mysqli_num_rows($entry_result) > 0){
$conn->query("UPDATE steplogger SET steps='$steps' WHERE userid='$user_id' AND date=NOW()");
} else {
$conn->query("UPDATE users SET totalsteps = totalsteps + ('$steps') WHERE username = '$user'");
$conn->query("INSERT INTO steplogger (steps, userid, date) VALUES ('$steps', '$user_id', NOW())");
}
Any thoughts on what I am doing wrong?
PS. When I echo $entry_result I get a mysqli object.
As you said :
I want to remove the option of having duplicate rows where user id and date
The best way is to create an UNIQUE index on user_id and date, this way you won't be able to insert two rows with same user_id and date.
With an UNIQUE index, you can use INSERT...ON DUPLICATE KEY UPDATE that will do what you want : you will insert a new row (new user_id + date) and if a row already exists with the same user_id and date, you will update the row.
Here is the documentation : https://dev.mysql.com/doc/refman/8.0/en/insert-on-duplicate.html
You can try like this
if (mysqli_num_rows($entry_result) > 0){
$conn->query("UPDATE steplogger SET steps='$steps' WHERE userid='$user_id' AND date=".NOW().")";
} else {
$conn->query("UPDATE users SET totalsteps = totalsteps + ('$steps') WHERE username = '$user'");
$conn->query("INSERT INTO steplogger (steps, userid, date) VALUES ('$steps', '$user_id', ".NOW()."))";
}
To get current date in NOW() function, you can use this function.
And also format of the two conditions should be same.

How to SELECT a record, UPDATE it and be sure it hasn't been updated in the mean?

I need to do something like that:
SELECT id FROM table WHERE option='1' ORDER BY time LIMIT 1
then with the id in $id
UPDATE table SET used='1' WHERE id='$id'
The problem is that this way another user can update the same record in the same time.
Is there a way to do that in one only operation ?
Thanks
UPDATE table SET used='1'
WHERE id=
(SELECT id FROM
(SELECT id FROM table
WHERE option='1'
ORDER BY time
LIMIT 1) AS tmptable
)
You need to use a three step query if you have concurrent access to the same row by different users.
First query has to reserve the row for a certain user (using a dedicated field).
Second query has to check if the row reservation is for that certain user.
Third query updates the row knowing there's no collision as that user reserved it.
Between step #1 and #2, multiple users can try to grab edit access to the row but in the end only one succeeds. The ones that failed will not reach step #3.
PS: This might be overkill for your needs but it's the best way to ensure multiple users work on tasks (rows) concurrently.
PPS: Or just combine the queries into a single one as another answer points out. But if your update requires some work done, it's best to decide upfront who will do the work before updating the value.
You could use: http://php.net/manual/en/mysqli.insert-id.php
mysql_insert_id
Finds the last id updated or set and stores it. We then check to make sure the last id does not exist.
so...
//last id being the id of the last query set or updated
$last_id = $mysql->insert_id;
if($last_id != $id) {
//execute code
{
else {
echo "last id already in database!";
}
If I misinterpreted the question you should still be able to see how to use that last id to do what you want.
Here is an example of it being used. First we update the table with the form data which created our ID. Then we add the input check boxes array to the last id updated.
//define input variables
$lesson_id = $_POST['lesson_id'];
$user_id = $_POST['user_id'];
$instructor_id = $_POST['instructor_id'];
$lesson_comments = $_POST['lesson_comments'];
$lesson_date = date("Y-m-d");
$video_ids = isset($_POST['checkbox']) ? $_POST['checkbox'] : array(); # this is called a ternary operator
//insert lesson information first
$query ="INSERT INTO swing_viewer_lessons (lesson_id, user_id, instructor_id, lesson_comments, lesson_date) VALUES (?, ?, ?, ?, ?)";
if ($stmt = $mysqli->prepare($query)) {
$stmt->bind_param("iiiss", $lesson_id, $user_id, $instructor_id, $lesson_comments, $lesson_date);
$stmt->execute();
//printf($stmt->error);
echo "successful";
//echo "$last_id";
}
//insert lesson information
if (is_array($video_ids) && count($video_ids) > 0)
{
foreach($video_ids as $list);
}
// Make it into a comma separated list
$rec_ids = implode(',', $video_ids);
//get last inserted id from above
$last_id= $mysqli->insert_id;
//finally query and update lesson information based on the last id added from above
$query ="UPDATE swing_viewer_lessons SET video_ids=? WHERE id=?";
if ($stmt = $mysqli->prepare($query)) {
$stmt->bind_param("si", $rec_ids, $last_id);
$stmt->execute();
}
Hopefully this helps you or anyone else for that matter, as at one point I was pulling hair at this.

insert mysql table results twice for duplicate results in multiple columns?

Would some one please help me, i have a block user script. Basically everything is working ok.
When the user clicks block on the other users profile, this echos the user id, and inserts the user_id and other profile_id into the database and sets the column 'blocked' from '0' to '1'.
the user who is logged in can now not see the other user they have blocked, however the other the user they blocked can still see their profile.
the way my database works is that it needs both sets id in both columns like so:
user_id | blocked_id | blocked
1 2 1
2 1 1
In order for both users to not see each other and both be blocked i need to try insert the two id's twice almost.
It's kind of like duplicating the values inserted into the table to create the same result twice but only the other way around in the table columns.
so at the moment i have:
$sql = mysql_query("INSERT INTO ptb_block_user (user_id, blocked_id) VALUES (".$_SESSION['user_id'].", ".$user_to_id.")");
and i would need to insert these values twice but the opposite way round so it looks like the table above.
I hope im making myself clear, does anyone know how i could do this?
Thanks.
<?php
session_start();
confirm_logged_in();
if (isset ($_GET['to'])) {
$user_to_id = $_GET['to'];
}
if (!isset($_GET['to']))
exit('No user specified.');
$user_id = $_GET['to'];
$sql = mysql_query("INSERT INTO ptb_block_user (user_id, blocked_id) VALUES (".$_SESSION['user_id'].", ".$user_to_id.")");
$result1 = mysql_query("UPDATE ptb_block_user SET blocked='1' WHERE user_id=".$_SESSION['user_id']."")
or die(mysql_error());
if($result1)
{
$_SESSION['message2']="<div class=\"infobox-profile\"><strong>User Blocked</strong> - This user has successfully been blocked. You will no longer be abler to interact with each other's profiles.</div><div class=\"infobox-close\"></div>";
header("Location: {$_SERVER['HTTP_REFERER']}");
}
else
if($result2)
{
$_SESSION['message2']="<div class=\"infobox-favourites\"><strong>User Unblocked</strong> - This user has successfully been unblocked. You can now interact with each other's profiles.</div><div class=\"infobox-close4\"></div>";
header("Location: {$_SERVER['HTTP_REFERER']}");
}
?>
Your question is not entirely clear to me, but it seems like you're asking how to insert both values with the same query. VALUES can take multiple tuples:
INSERT INTO ptb_block_user (user_id, blocked_id, blocked) VALUES
(".$_SESSION['user_id'].", ".$user_to_id.", 1),
(".$user_to_id.", ".$_SESSION['user_id'].", 1)
Your code is highly vulnerable to mysql injection, and you should not use ext/mysql:
http://www.php.net/manual/en/faq.databases.php#faq.databases.mysql.deprecated
INSERT INTO ptb_block_user
(user_id, blocked_id)
VALUES
(".$_SESSION['user_id'].", ".$user_to_id."),
(".$user_to_id.",".$_SESSION['user_id'].")
?

Syntax error with IF EXISTS UPDATE ELSE INSERT

I'm using MySQL 5.1 hosted at my ISP. This is my query
mysql_query("
IF EXISTS(SELECT * FROM licensing_active WHERE title_1='$title_1') THEN
BEGIN
UPDATE licensing_active SET time='$time' WHERE title_1='$title_1')
END ELSE BEGIN
INSERT INTO licensing_active(title_1) VALUES('$title_1')
END
") or die(mysql_error());
The error is
... check the manual that corresponds to your MySQL server version for the right syntax to use near 'IF EXISTS(SELECT * FROM licensing_active WHERE title_1='Title1') THEN ' at line 1
My actual task involves
WHERE title_1='$title_1' AND title_2='$title_2' AND version='$version' ...ETC...
but I have reduced it down to make things simpler for my problem solving
In my searches on this, I keep seeing references to 'ON DUPLICATE KEY UPDATE', but don't know what to do with that.
Here is a simple and easy solution, try it.
$result = mysql_query("SELECT * FROM licensing_active WHERE title_1 ='$title_1' ");
if( mysql_num_rows($result) > 0) {
mysql_query("UPDATE licensing_active SET time = '$time' WHERE title_1 = '$title_1' ");
}
else
{
mysql_query("INSERT INTO licensing_active (title_1) VALUES ('$title_1') ");
}
Note: Though this question is from 2012, keep in mind that mysql_* functions are no longer available since PHP 7.
This should do the trick for you:
insert into
licensing_active (title_1, time)
VALUES('$title_1', '$time')
on duplicate key
update set time='$time'
This is assuming that title_1 is a unique column (enforced by the database) in your table.
The way that insert... on duplicate works is it tries to insert a new row first, but if the insert is rejected because a key stops it, it will allow you to update certain fields instead.
The syntax of your query is wrong. Checkout http://dev.mysql.com/doc/refman/5.0/en/control-flow-functions.html
Use the on duplicate key syntax to achieve the result you want. See http://dev.mysql.com/doc/refman/5.0/en/insert-select.html
Another solution
$insertQuery = "INSERT INTO licensing_active (title_1) VALUES ('$title_1')";
if(!$link->query($insertQuery)){ // Insert fails, so update
$updateQuery = "UPDATE licensing_active SET time='$time' WHERE title_1='$title_1'";
$link->query($updateQuery);
}
Here is the example I tried and its works fine:
INSERT INTO user(id, name, address) VALUES(2, "Fadl", "essttt") ON DUPLICATE KEY UPDATE name = "kahn ajab", address = "Address is test"
I am amazed to see so many useless codes and answers...
Just replace INSERT with REPLACE.
¯\(ツ)/¯

Select from table, and insert data to another - Multiply data -SQL

I have a button that will delete all users that fits into this query:
DELETE FROM users WHERE lastlogin < ".time()." - ".$sdata['activitylimit']."*3600
Although, I have to take some parts of each users data, and put it into another table ("username" and "email")
How can I take the users username AND email from the table users, and insert it into my table "reserved_data"?
The table reserved_data looks like this:
id (just the id)
data (the email or username value)
type (what type of data is it((username/email)))
You can't do that directly, thanks to the table layout of the reserved_data table. Why do you do that? Why haven't you got a deleted_users table, containing their username and email? That way you could do this:
$q1 = "INSERT INTO deleted_users (username, email) SELECT username, email FROM users WHERE lastlogin < (".time()." - ".$sdata['activitylimit']." * 3600)";
$q2 = "DELETE FROM users WHERE lastlogin < (".time()." - ".$sdata['activitylimit']." * 3600)";
If you won't change the table, use something like this:
$toDelete = mysql_query("SELECT username, email FROM users WHERE lastlogin < (".time()." - ".$sdata['activitylimit']." * 3600)");
while($user = mysql_fetch_assoc($toDelete))
{
mysql_query("INSERT INTO reserved_data (`data`, `type`) VALUES ('" . $user['username'] . ", 'username'");
mysql_query("INSERT INTO reserved_data (`data`, `type`) VALUES ('" . $user['email'] . ", 'email'");
}
// Now perform the delete
mysql_query("DELETE FROM users WHERE lastlogin < (".time()." - ".$sdata['activitylimit']." * 3600)");
You see the latter requires more code and is generally a bad idea. You lose the relation between a username and its email address.
Besides, you might want to use transactions, since it's possible for one to not be included in the first query but be included in the second query. You then lose this user's data.
And perhaps you can fix all your problems by simply adding an (in)active column to your users table. One rarely wants to really delete data.
Also you can use on delete trigger to log data to reserved_data table. Just move your reserved_data insert to trigger
I would not recommend approach with deletion mark. You don't need it there is no requirement to restore deleted users and it brings quite much new problems.

Categories