I have a datatable with user information and a column called 'Bits'. There is a transfer function and I would like to transfer x amount of bits from the logged in user to the user they specify. I have the following function that works, but I would like to know if there is a better (simpler, cleaner, quicker?) way to do all of this, and possibly return the row of the first SQL statement at the end. I am not an advanced MySQL user by any means, but I am pretty sure there is a function I am missing that could make this much easier.
function transferBits($toid, $amount)
{
global $loggedInUser, $db;
$fromid = $loggedInUser->user_id;
$sql = "INSERT INTO `dl_Transfers` SET From_ID = '".$db->sql_escape($fromid)."',
`To_ID`='".$db->sql_escape($toid)."',
`Bits`='".$db->sql_escape($amount)."',
`When`=Now()";
$result = $db->sql_query($sql);
$sql2 = "UPDATE `dl_Users` SET Bits = Bits - '".$db->sql_escape($amount)."' WHERE `User_ID` = '".$db->sql_escape($fromid)."'";
$result2 = $db->sql_query($sql2);
$sql3 = "UPDATE `dl_Users` SET Bits = Bits + '".$db->sql_escape($amount)."' WHERE `User_ID` = '".$db->sql_escape($toid)."'";
$result3 = $db->sql_query($sql3);
}
I think you could hit the update in single query by joining on the previous record id from your insert on dl_Transfers:
UPDATE `dl_Transfers` r
JOIN `dl_Users` f ON ( r.From_ID = f.User_ID )
JOIN `dl_Users` t ON ( r.To_ID = t.User_ID )
SET f.Bits = f.Bits - r.Bits, t.Bits = t.Bits + r.Bits
WHERE r.Transfer_ID = ?;
Also as others stated in their comments, you should definitely use transactions here.
You might consider using a MySQL trigger to handle this. Basically, you would set it up so anytime there is an insert on dl_Transfers, it updates the appropriate rows in dl_Users.
http://dev.mysql.com/doc/refman/5.0/en/triggers.html
Related
I'm trying to update two tables at the same time. The action completes successfully.However, it updates all records in the the table instead of the ones specified. I have tried the suggestions here, but to no avail. Any ideas what the issue might be? My code looks like below.
$sql = "UPDATE $receiverTable, $currUserTable
SET $currUserTable.originator = '$curr_username',
$receiverTable.originator = '$curr_username',
$currUserTable.status = '$currValue',
$receiverTable.status = '$currValue'
WHERE ($receiverTable.username = '$curr_username')
OR ($currUserTable.username = '$curr_username')";
You have no condition on your JOIN (you really shouldn't be writing JOINs with commas any more) and so every row gets JOINed to every other row, which means that they all have a JOIN to a row in which one of the WHERE conditions is true, hence they all get updated. Rewrite your JOIN with the appropriate condition and the problem will go away. Something like:
UPDATE $receiverTable
JOIN $currUserTable ON $currUserTable.somecolumn = $receiverTable.somecolumn
SET $currUserTable.originator = '$curr_username',
$receiverTable.originator = '$curr_username',
$currUserTable.status = '$currValue',
$receiverTable.status = '$currValue'
WHERE ($receiverTable.username = '$curr_username')
OR ($currUserTable.username = '$curr_username')
If there is no way that the tables can be JOINed, you will need to write the UPDATE as two separate queries.
Instead of doing this with a single update use a transaction to wrap two update commands, something like this.
BEGIN TRANSACTIONS;
UPDATE TABLE1
SET Col1 = 'SomeValue'
WHERE Cond1 = 'SomeCond';
UPDATE TABLE2
SET Col2 = 'SomeValue'
WHERE Cond2 = 'SomeCond';
COMMIT;
UPDATE
Following this I believe with phpi it would look like:
mysqli_autocommit($dbConnection, false);
$query1 = " UPDATE $receiverTable set originator = '$curr_username',
status = '$currValue' WHERE username = '$curr_username' "
$query2 = " UPDATE $currUserTable set originator = '$curr_username',
status = '$currValue' WHERE username = '$curr_username' "
mysqli_query($dbConnection, $query1);
mysqli_query($dbConnection, $query2);
mysqli_commit($dbConnection);
I am trying to loop through an array ($lineup_selected) that corresponds to a player row in a database. For each player I would like to execute an UPDATE query to the database that adds the value of $submissions_selected to the total_picks column. I am struggling with the code as it fails to execute the query. Any help please?!
// Select team & formation
$team_selected = "team1";
$lineup_selected = array("player1", "player2", "player3");
$submissions_selected = 4000;
// Loop through and update total_picks for each player in database present in lineup_selected array
$player_picks_query = "SELECT full_name, total_picks FROM table WHERE team=$team_selected";
$result = mysqli_query($conn, $player_picks_query);
while($row = mysqli_fetch_assoc($result)) {
$player = mysql_real_escape_string($row["full_name"]);
$add_player_picks = "UPDATE table
SET total_picks = total_picks + $submissions_selected
WHERE full_name = '$player'";
}
why not:
UPDATE table
SET total_picks = total_picks + $submissions_selected
WHERE team = '$team_selected'
this way you have only one query to execute and let your database do the looping. Else you would first select some records and then have your database update each one of them to update the record.
I assume the fullname is unique. If not, it would mean your version can have the update-query modify multiple records each time and so my approach is invalid
-- and I seem to repeat a lot of the comments when stating to sanitize and escape your input to be save(r).
edit:
combined it should come to:
// set team & formation
$team_selected = "team1";
$lineup_selected = array("player1", "player2", "player3");
$submissions_selected = 4000;
$updatequery = "UPDATE table
SET total_picks = total_picks + ?
WHERE team= ?";
$stmt = mysqli_prepare($updatequery);
mysqli_stmt_bind_param($stmt, "is", $submissions_selected, $team_selected);
/* execute prepared statement */
mysqli_stmt_execute($stmt);
Myself I am more into the pdo approach, but syntax should be like this.
In your select request you have a team that is obviously a String. So, maybe you can try your request like : "SELECT full_name, total_picks FROM table WHERE team='$team_selected'"
I don't know if PHP is smart enough to put the quotes.
I think it will be better if you use only an update statement.
First of all you implode your array
$lineup_selected = array("player1", "player2", "player3");
$players='".implode("','",$lineup_selected )."';
Now you can update the table
$updateStmt="UPDATE table
SET total_picks = total_picks + $submissions_selected
WHERE full_name in (".$players.") and team=".$team_selected.";
I updated with success
$result = mysql_query("UPDATE $table SET `queue2` = `queue2` + 1 WHERE `id` = '$getid'");
but how can I get the "queue2" value without opening a new request to MySQL
I can simply get the new value with this command
$selresult = mysql_query("SELECT * FROM $table WHERE `id` = '$getid'") or die(mysql_error());
but I'm afraid that the database can get new update again and i will get higher number
Any idea how to do it ?
you can use query to update the value.
mysql_query("UPDATE user_profile SET userpoints = userpoints + 1 WHERE user_id = '".$user_id."'");
See URL:-
PHP + MySQL transactions examples
Try this:-
printf ("Updated records: %d\n", mysql_affected_rows());
mysql_query("COMMIT");
You will need to use a transaction between the queries to be certain.
The docs for transactions are here. A good SO question that covers it in detail: PHP + MySQL transactions examples
Edit:
Looking at it from a different angle, why don't you do it in reverse though? It might save the need for a transaction (thought it is possible that you get multiple reads before a write):
Get the value for your queue2 value to display in the page from this:
mysql_query("SELECT * FROM $table WHERE `id` = '$getid'");
You have the true value now, so you can run:
$result = mysql_query("UPDATE $table SET `queue2` = `queue2` + 1 WHERE `id` = '$getid'");
No transaction and you know the value of the data before the update.
i want to combine a SELECT and UPDATE query, to avoid duplicat select of rows.
Here is my example code:
private function getNewRCode() {
$getrcodesql = "SELECT * FROM `{$this->mysqlprefix}codes` WHERE `used` = 0 LIMIT 1;";
$getrcodequery = $this->mysqlconn->query($getrcodesql);
if(#$getrcodequery->num_rows > 0){
$rcode = $getrcodequery->fetch_array();
$updatercodesql = "UPDATE `{$this->mysqlprefix}codes` SET `used` = '1' WHERE `id` = {$rcode['id']};";
$this->mysqlconn->query($updatercodesql);
$updateusersql = "UPDATE `{$this->mysqlprefix}users` SET `used_codes` = `used_codes`+1, `last_code` = '{$rcode['code']}', `last_code_date` = NOW() WHERE `uid` = {$this->uid};";
$this->mysqlconn->query($updateusersql);
$output = array('code' => $rcode['code'],
'time' => time() + 60*60*$this->houroffset,
'now' => time()
);
return $output;
}
}
I would like to execute $getrcodesql and $updatercodesql at once, to avoid that the same code is used for different users.
I hope you understand my problem and know a solution for this.
Greetings,
Frederick
It's easier if you do it the other way round.
The point is that that your client can generate a unique value before you do the UPDATE and SELECT.
Change the type of your used column to something else, so that you can store a GUID or a timestamp in it, and not just 0 and 1.
(I'm not a PHP/MySQL expert, so you probably know better than me what exactly to use)
Then you can do this (in pseudocode):
// create unique GUID (I don't know how to do this in PHP, but you probably do)
$guid = Create_Guid_In_PHP();
// update one row and set the GUID that you just created
update codes
set used = '$guid'
where id in
(
select id
from codes
where used = ''
limit 1
);
// now you can be sure that no one else selected the row with "your" GUID
select *
from codes
where used = '$guid'
// do your stuff with the selected row
I have the following 3 tables in the database.
Programs_Table
Program_ID (Primary Key)
Start_Date
End_Date
IsCompleted
IsGoalsMet
Program_type_ID
Programs_Type_Table(different types of programs, supports a dropdown list in the form)
Program_type_ID (Primary Key)
Program_name
Program_description
Client_Program_Table
Client_ID (primary key)
Program_ID (primary key)
What is the best way to find out how many clients are in a specific program (program type)?
Would the following SQL statement be the best way, or even plausible?
SELECT Client_ID FROM Client_Program_Table
INNER JOIN Programs_Table
ON Client_Program_Table.Program_ID = Programs_Table.Program_ID
WHERE Programs_Table.Program_type_ID = "x"
where "x" is the Program_type_ID of the specific program we're interested in.
OR is the following a better way?
$result = mysql_query("SELECT Program_ID FROM Programs_Table
WHERE Program_type_ID = 'x'");
$row = mysql_fetch_assoc($result);
$ProgramID = $row['Program_ID'];
$result = mysql_query("SELECT * FROM Client_Program_Table
WHERE Program_ID = '$ProgramID'");
mysql_num_rows($result) // returns how many rows of clients we pulled.
Thank you in advance, please excuse my inexperience and any mistakes that I've made.
Here is how you can do it:
<?php
// always initialize a variable
$number_of_clients = 0;
// escape the string which will go in an SQL query
// to protect yourself from SQL injection
$program_type_id = mysql_real_escape_string('x');
// build a query, which will count how many clients
// belong to that program and put the value on the temporary colum "num_clients"
$query = "SELECT COUNT(*) `num_clients` FROM `Client_Program_Table` `cpt`
INNER JOIN `Programs_Table` `pt`
ON `cpt`.`Program_ID` = `pt`.`Program_ID`
AND `pt`.`Program_type_ID` = '$program_type_id'";
// execute the query
$result = mysql_query($query);
// check if the query executed correctly
// and returned at least a record
if(is_resource($result) && mysql_num_rows($result) > 0){
// turn the query result into an associative array
$row = mysql_fetch_assoc($result);
// get the value of the "num_clients" temporary created column
// and typecast it to an intiger so you can always be safe to use it later on
$number_of_clients = (int) $row['num_clients'];
} else{
// query did not return a record, so we have no clients on that program
$number_of_clients = 0;
}
?>
If you want to know how many clients are involved in a program, you'd rather want to use COUNT( * ). MySQL (with MyISAM) and SQL Server have a fast way to retrieve the total number of lines. Using a SELECT(*), then mysql_num_rows leads to unnecessary memory ressources and computing time. To me, this is the fastest, though not the "cleanest" way to write the query you want:
SELECT
COUNT(*)
FROM
Client_Program_Table
WHERE
Program_ID IN
(
SELECT
Program_ID
FROM
Programs_Table
WHERE
Program_type_ID = 'azerty'
)
Why is that?
Using JOIN make queries more readable, but subqueries often prove to be computed faster.
This returns a count of the clients in a specific program type (x):
SELECT COUNT(cpt.Client_ID), cpt.Program_ID
FROM Client_Program_Table cpt
INNER JOIN Programs_Table pt ON cpt.Program_ID=pt.Program_ID
WHERE pt.Program_type_ID = "x"
GROUP BY cpt.Program_ID