I have a highscores table, it seems to be working fine apart from the problem of at random times it seems to be resetting certain users back to 0, this is my query:
$user = isset($_GET['username']) ? $_GET['username'] : "";
$time = isset($_GET['time']) ? $_GET['time'] : "";
$videos = isset($_GET['videos']) ? $_GET['videos'] : "";
$credits = isset($_GET['credits']) ? $_GET['credits'] : "";
$user = mysql_real_escape_string($user);
$time = mysql_real_escape_string($time);
$videos = mysql_real_escape_string($videos);
$credits = mysql_real_escape_string($credits);
$secret = mysql_real_escape_string($secret);
// Main Query
$retval = mysql_query("
INSERT INTO
highscores(Username, Time, Videos, Credits)
VALUES
('$user', '$time', '$videos', '$credits')
ON DUPLICATE KEY UPDATE
Time = '$time',
Videos = '$videos',
Credits = '$credits'
",
$conn
);
It updates fine most of the time, can anyone see what the problem is?
I guess you want to update the credit and not zero it.
Say you set $credit to 0 before you execute the query, than the ON DUPLICATE KEY UPDATE part will cause the current user credits to be zeroed. Instead you should do something like this:
<?php
$user = 109;
$time = time();
$videos = 'something';
$credits = 0;
$retval = mysql_query("INSERT INTO
highscores
(Username, Time, Videos, Credits)
VALUES
('$user', '$time', '$videos', '$credits')
ON DUPLICATE KEY UPDATE
Time = '$time',
Videos = '$videos',
Credits = Credits + 1", $conn);
I think you are looking for
$query = sprintf("INSERT INTO highscores(Username, Time, Videos, Credits)
VALUES('%s', '%s', '%s', '%s')
ON DUPLICATE KEY UPDATE Time = Time + %2$s, Videos = Videos + %3$s, Credits = Credits + %4$s"
mysql_real_escape_string($user), // escape every variable you will be using in
mysql_real_escape_string($time), // an SQL query to protect yourself against
mysql_real_escape_string($videos), // SQL injection or use parametriezed
mysql_real_escape_string($credits)); // queries with wrappers such as PDO or MySQLi
$retval = mysql_query($query,$conn);
If a user exists already, this will just add to the current Credits the new value, but it won't change anything else. This seems logical to me. If you also need to increment other columns such as Videos, do the same thing I did for the Credits.
Other have pointed what causes this behaviour. Here's an alternative syntax for the ON DUPLICATE UPDATE
// Main Query
$retval = mysql_query("
INSERT INTO highscores
(Username, Time, Videos, Credits)
VALUES
('$user', '$time', '$videos', '$credits')
ON DUPLICATE KEY UPDATE
Time = Time + VALUES(Time),
Videos = Videos + VALUES(Videos),
Credits = Credits + VALUES(Credits)
",
$conn
);
Related
I have a system where the user sends an invitation, and once the official accepts, it will be saved to the database and sync to the official's calendar.
I'm trying to run a query where it checks if there are any events on that current time. Basically if it returns at least 1, it means the invitation wont send because there is a conflict but it just ignores the row count from MySQL database. Here is my code:
// variables
$id = $_GET['id'];
$dStart = $_POST['dStart'];
$dEnd = $_POST['dEnd'];
$time = $_POST['time'];
$time_end = $_POST['time_end'];
// convert them into date formats
$date = date("Y-m-d", strtotime($dStart));
$date2 = date("Y-m-d", strtotime($dEnd));
$time_f = date("H:i:s", strtotime($time));
$time_end_f = date("H:i:s", strtotime($time_end));
// set default timezone
date_default_timezone_set('Asia/Manila');
// check if date is occupied
$query_check = mysqli_query($con, "SELECT COUNT(*) as total FROM events WHERE (date_start = '$date') AND ((`time` BETWEEN '$time_f' AND '$time_end_f') OR (`time_end` BETWEEN '$time_f' AND '$time_end_f')) AND pastor_id = '$id' AND invite = 0 AND reschedule = 0") or die (mysqli_error($con));
$fetch_check = mysqli_fetch_array($query_check);
if ($fetch_check['total'] >= 1) {
echo "<center><p>Sorry, this time is occupied. Please select another schedule</p><p>If you haven't, please refer to this pastor's calendar which can be found by <a href='profile.php?id=$id&grid=true'>clicking here.</a></p></center>";
} else {
// generate random reference code
$ref_code = rand(1000000, 9999999);
$_SESSION['reference_code'] = $ref_code;
$ref_code_final = $_SESSION['reference_code'];
// insert to events table
$query = mysqli_query($con, "INSERT INTO `events` (`id`, `reference_code`, `name`, `description`, `date_start`, `date_end`, `time`, `time_end`, `pastor_id`, `pastor`, `category`, `venue`, `invite`, `sender_name`, `sender_address`, `sender_phone`) VALUES (NULL, '$ref_code_final', '$name', '$description', '$date', '$date2', '$time', '$time_end', '$id', '$pastor', '$category', '$venue', '1', '$sender', '$address', '$phone')");
header("Location: send.php?sendid=$id&success");
}
I checked so many times on PHPMyAdmin, the query returns at least 1 from my database. I made another .php file and ran the query there, echoed the result and it still outputs 1. But for some reason, when I use the query here it COMPLETELY ignores the if statement and goes directly to else
I'm making an Android app that connects to a database online and lets the user edit the database from the application, I'm new to PHP and MySql but from my research I think I should be using an UPDATE statement, I've written the code below to register new users on the site from a tutorial, but I'd like to change the INSERT statement to an UPDATE statement so that instead of registering a new user, the App updates existing data that I have entered in PHPMYADMIN, could someone show me how to do this? Also, if you require the code for the app mention it in the comments and I'll add it to the question, I don't want to post too much unneccessary code. Thanks in advance.
<?php
require "conn.php";
$patient_name = $_POST["patient_name"];
$check_in_date = $_POST["check_in_date"];
$room_number = $_POST["room_number"];
$bed_number = $_POST["bed_number"];
$notes = $_POST["notes"];
$mysql_qry = "insert into patients(patient_name, check_in_date, room_number, bed_number, notes) values ('$patient_name', '$check_in_date', '$room_number', '$bed_number', '$notes')";
if($conn->query($mysql_qry) === TRUE) {
echo "Insert successful";
}
else{
echo "Error: " . $mysql_qry . "<br>" . $conn->error;
}
$conn->close();
?>
EDIT
The fixed code is below, it now updates records already in the database rather than adding new data.
<?php
require "conn.php";
$patient_name = $_POST["patient_name"];
$check_in_date = $_POST["check_in_date"];
$room_number = $_POST["room_number"];
$bed_number = $_POST["bed_number"];
$notes = $_POST["notes"];
$mysql_qry = "UPDATE patients SET notes='$notes' WHERE patient_name='$patient_name'";
if($conn->query($mysql_qry) === TRUE) {
echo "Insert successful";
}
else{
echo "Error: " . $mysql_qry . "<br>" . $conn->error;
}
$conn->close();
?>
first of all this PHP code is vulnerable to sql injection you should, no need to update your code to use either mysqli prepared statement or PDO prepared statement
secondly the easiest way I know you accomplish your goal would make a unique constraint on some columns and then use a mysql feature ON DUPLICATE UPDATE
for this example I'll assume that the unique fields determining an update instead of an insert are patient_name, check_in_date, room_number, and bed_number (in case john smith was in the same room as john smith in seprate beds) the query to update the table would be like this
ALTER TABLE `patients` ADD UNIQUE `unique_index`(`patient_name`, `check_in_date`, `room_number`, `bed_number`);
so now to address the sql injection bit and the query, I'll update the example to use mysqli statement and will assume patient_name and notes are strings (varchar/nvarchar), room_number and bed_number are integers, and check_in_date is a date
Edit My original answer had a syntax error in the query and also passing variables to the prepared statement below is the updated answer
$mysqliConn = new mysqli("localhost", "my_user", "my_password", "mydatabase");
$stmt = $mysqliConn->prepare("insert into patients
(patient_name, check_in_date, room_number, bed_number, notes)
values (?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE notes=values(notes)");
$patient_name = $_POST["patient_name"];
$check_in_date = $_POST["check_in_date"];
$room_number = $_POST["room_number"];
$bed_number = $_POST["bed_number"];
$notes = $_POST["notes"];
mysqli_stmt_bind_param($stmt, "sdiis",
$patient_name, $check_in_date, $room_number, $bed_number, $notes);
hope this helps
Edit
Regarding the unique key, a unique key means that all fields in the unique key have to be unique when combined so for the example above
if record 1 is
patient_name, check_in_date, room_number, bed_number, notes
'john smith', '3/1/2017' , 413 , 2 , 'patient is sick'
and record two is
'jane doe' , '3/1/2017' , 413 , 2 , 'patient has wound'
these two records will note be duplicates with the above constraint but if you do need to change the constraint you can do the following
DROP the Constraint
ALTER TABLE `patients` DROP INDEX `unique_index`;
Then recreate the constraint like this
ALTER TABLE `patients` ADD UNIQUE `unique_index`(`patient_name`, `check_in_date`, `room_number`);
also if you named your constraint something other than unique_index you can find the key_name by running the following
SHOW INDEX FROM `patients`;
the name will be in the key_name column
additionally you may want to alter the last line of the query to be this in your php if you change the unique constraint so you can change bed number
ON DUPLICATE KEY UPDATE bed_number=values(bed_number), notes=values(notes)
You can also use REPLACE INTO, then you don't have to change the SQL statement. Let MySQL do the work for you.
https://dev.mysql.com/doc/refman/5.7/en/replace.html
<?php
require "conn.php";
$patient_name = $_POST["patient_name"];
$check_in_date = $_POST["check_in_date"];
$room_number = $_POST["room_number"];
$bed_number = $_POST["bed_number"];
$notes = $_POST["notes"];
$mysql_qry = "REPLACE INTO patients(patient_name, check_in_date, room_number, bed_number, notes) VALUES ('$patient_name', '$check_in_date', '$room_number', '$bed_number', '$notes')";
if($conn->query($mysql_qry) === TRUE) {
echo "Insert successful";
}
else{
echo "Error: " . $mysql_qry . "<br>" . $conn->error;
}
$conn->close();
Also, you should really take a look at using PDO with prepared statements and parameters.
https://secure.php.net/manual/en/pdo.prepare.php
Actually I was looking for a small function that converts an INSERT MySQL query to an UPDATE query. So maybe other people were looking for the same and I think this is what the original poster was looking for aswell... I couldnt find any so I made this simple function which works for my needs, ofcourse you will have to make sure your original query is safe from MySQL injection.
It will convert
INSERT INTO aaa (bbb, ccc) VALUES ('111', '222')
to
UPDATE aaa SET ccc='222' WHERE bbb='111'
Use the 2nd variable ($iColumn) to identify the WHERE statement.
function convertInsertToUpdate($sQuery, $iColumn = 1) {
$sNewQuery = "";
$iPos = strpos($sQuery, ' (');
$sTmpTable = substr($sQuery, 0, $iPos);
$iPos = strpos($sTmpTable, 'INSERT INTO ');
$sTmpTable = substr($sTmpTable, $iPos+12);
$iPos = strpos($sQuery, ') VALUES (');
$sTmpValues = substr($sQuery, $iPos+10);
$iPos = strrpos($sTmpValues, ')');
$sTmpValues = substr($sTmpValues, 0, $iPos);
$iPos = strpos($sQuery, '(');
$sTmpColumns = substr($sQuery, $iPos+1);
$iPos = strpos($sTmpColumns, ') VALUES (');
$sTmpColumns = substr($sTmpColumns, 0, $iPos);
$aColumns = explode(', ', $sTmpColumns);
$aValues = explode(', ', $sTmpValues);
if (count($aColumns)>0 && count($aColumns) == count($aValues) && $iColumn < (count($aValues)+1)) {
$sNewQuery = "UPDATE ".$sTmpTable." SET";
$sTmpWhere = "";
$bNotFirst = false;
$iX = 0;
while ($iX<count($aColumns)) {
if ($iColumn == ($iX+1)) {
$sTmpWhere = " WHERE ". $aColumns[$iX]."=".$aValues[$iX];
$iX++;
continue;
}
if ($bNotFirst) {
$sNewQuery .= ",";
}
$sNewQuery .= " ".$aColumns[$iX]."=".$aValues[$iX];
$bNotFirst = true;
$iX++;
}
$sNewQuery .= $sTmpWhere;
}
return $sNewQuery;
}
I have a website for fantasy golf. I use php to read an xml file and update the sql database using the following
foreach($field->field->children() as $player){
$lastname = ($player['last_name']);
$firstname = ($player['first_name']);
$firstname = mysql_real_escape_string($firstname);
$lastname = mysql_real_escape_string($lastname);
$sSQL = "UPDATE `Sheet1` Set InField= 1 WHERE LastName = '$lastname' AND Firstname = '$firstname'";
$result = mysql_query($sSQL, $conn) or die(mysql_error());
This updates the database INFIELD column with the players on the xml file. My question is how would I go about adding that player to the database if he isn't in it already? So almost like doing and if not in the database--insert new record?
any help would be appreciated.
Make sure you have a unique key on (LastName, FirstName), then use:
INSERT INTO Sheet1 (LastName, FirstName, InField)
VALUES ('$lastname', '$firstname', 1)
ON DUPLICATE KEY UPDATE InField = 1
Documentation
I suggest you condition it.
player =mysql_query(select player_in_table from players_table where player_in_table = playerx)
if(mysql_num_row(player) = 1){
//update
} else {
//update
}
I get the error: Column 'Time' cannot be null when using the query below, it works fine the first time when there is no duplicate but then when trying to update again I get the error: Column 'Time' cannot be null
mysql_query("
INSERT INTO
$table(Username, Time, Videos, Credits)
VALUES
('$user', '$time', '$videos', '$credits')
ON DUPLICATE KEY UPDATE
Time=Time+INTERVAL $time SECOND
Videos=Videos+'$videos',
Credits=Credits+'$credits'
",
$conn
);
Hope you can spot my error as I am new to this, thanks!
Here is some more of my code:
$conn = mysql_connect(DB_HOST,DB_USER,DB_PASSWORD);
mysql_select_db(DB_NAME, $conn);
// Error checking
if(!$conn) {
die('Could not connect ' . mysql_error());
}
// Localize the GET variables
$user = isset($_GET['username']) ? $_GET['username'] : "";
$time = isset($_GET['time']) ? $_GET['time'] : "";
$videos = isset($_GET['videos']) ? $_GET['videos'] : "";
$credits = isset($_GET['credits']) ? $_GET['credits'] : "";
// Protect against sql injections
$user = mysql_real_escape_string($user);
$time = mysql_real_escape_string($time);
$videos = mysql_real_escape_string($videos);
$credits = mysql_real_escape_string($credits);
$secret = mysql_real_escape_string($secret);
// Insert
$retval = mysql_query("
INSERT INTO
$table(Username, Time, Videos, Credits)
VALUES
('$user', '$time', '$videos', '$credits')
ON DUPLICATE KEY UPDATE
Time = DATE_ADD(IFNULL(Time,now()),INTERVAL '$time' SECOND),
Videos = Videos+'$videos',
Credits = Credits+'$credits'
",
$conn
);
// End Query
if($retval) {
echo "Success! Updated $user with Time: $time - Videos: $videos - Credits: $credits";
} else {
echo "<b>ERROR:</b><br>" . mysql_error();
}
mysql_close($conn);
It should be:
mysql_query("
INSERT INTO
$table(Username, `Time`, Videos, Credits)
VALUES
('$user', '$time', '$videos', '$credits')
ON DUPLICATE KEY UPDATE
Time = DATE_ADD(IFNULL(`Time`,now()),INTERVAL '$time' SECOND)
,Videos = Videos+'$videos'
,Credits = Credits+'$credits'
",
$conn
);
Don't forget to put single quotes around all injected variables, otherwise mysql_real_escape_string will not protect you.
See:
http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_date-add
If there's no duplicate, then this query will do an insert, and the Time value will be null, as no value was ever set. Null + anything is null, hence the error.
Try ... Time = COALESCE(Time, 0) + INTERVAL $time SECOND or similar to get aroun dit.
I’ve created a little weekly trivia game for my website. Basically its five questions, then at the end the user can add their score to a scoreboard.
The problem is that I want the scores to carry from week to week and cumulate. So let’s say you got 4 points one week, then 5 points the next. I want the scoreboard to reflect you have 9 points.
So I created a small form with an i
nvisible field that has the users score, a field for the username, and a field for the e-mail address. Next week, when the user takes the quiz again, I want their score to be updated if the username and e-mail match a record in the database. If no record does match, I want an entry to be created.
Here’s the script I came up with, however, it doesn’t work (which doesn’t surprise me, I’m pretty new to PHP/MySQL)
$name = $_POST['name']; //The Username
$score = $_POST['submitscore']; //The users score (0-5)
$email = $_POST['email'];//Users email address
$date = date("F j, Y, g:i a");//The date and time
if($name != '') {
$qry = "SELECT * FROM scoreboard WHERE name='$name'";
$result = mysql_query($qry);
if($result) {
if(mysql_num_rows($result) > 0) {
$sum = ($row['SUM(score)']+$score);
"UPDATE scoreboard SET score = '$sum' WHERE name = '$name'";
}
else
$q = mysql_query("INSERT INTO scoreboard (`name`, `email`, `date`, `score`) VALUES ('$name', '$email', '$date', '$score');");
#mysql_free_result($result);
}
else {
die("Query failed");
}
}
My table scoreboard looks like this
id........name........email...........date...........score
1........J.Doe.....j.doe#xyz.com.....7/27/11.........4
You're looking for INSERT... ON DUPLICATE KEY syntax
"INSERT INTO scoreboard (`name`, `email`, `date`, `score`) ".
" VALUES ('$name', '$email', '$date', '$score') ".
"ON DUPLICATE KEY UPDATE `score` = $sum";
Aside:
Use mysql_real_escape_string!
$name = mysql_real_escape_string( $_POST['name'] );
$score = mysql_real_escape_string( $_POST['submitscore'] );
$email = mysql_real_escape_string( $_POST['email'] );
$date = date("F j, Y, g:i a");//The date and time
EDIT
First, this doesn't really work unless you have a column SUM(SCORE):
$sum = ($row['SUM(score)']+$score);
If you want the sum of a column, you need to put that in the MySQL query directly. If you just want the score for that row, however, you can use $row['score']. If you need to add to an existing score you don't need to select for the value (thanks to a1ex07 for pointing this out)
ON DUPLICATE KEY UPDATE `score` = $score + score
This line is incorrect:
$sum = ($row['SUM(score)']+$score);
You probably want to replace it by:
$sum = ($row['score']+$score);
As you are new to PHP/MySQL I recommend you to read about MySQL Injections as your queries contain potential risks.
I'd have a database table to hold quizzes; a database table for members; and a database table that contains foreign keys to both tables along with a score so only one record can be created for each member and each quiz.
I'd also save the score in a session when the user finishes the quiz so the user can't then just submit any old score to your database; the score entered is the score your application generated.
This way, you can then just query SUM(score) of a member based on that member's ID.