MySQL Determine if Query Run when No Change to DB Fields - php

I want to determine if this script was run regardless if there was a change to the database.
For Example:
1) If name was previously "Joe" then $rowsAffect returns the 'correct' answer "1".
2) If name was previously "Bob" then $rowsAffect returns the 'INCORRECT' answer "0".
Is there a variable I can use that will tell me the script was run?
$query = "UPDATE table
SET name='Bob'
WHERE id=25";
$result = $link->query($query);
$rowsAffect = mysqli_affected_rows($link);

It you really care about updating rows, then you can add another column, something like LastUpdatedDate:
alter table t add column LastUpdatedDate datetime;
update table t
set name = 'Bob', LastUpdatedDate = now()
where id = 25;
This guarantees that the row is updated, so you will see a row count.
Of course, if you run the query and it doesn't fail, then it really did run.

Related

Check which columns were modified in an UPDATE query

When we update a MySQL record with php, we can check if it has effect using:
$mysqli->affected_rows;
But how do I check which column has been modified?
Example, in my table have the columns: id / name / age
In a record we have the data: 1 / Woton / 18
If I send an: UPDATE mytable SET name = 'Woton', age = '20' WHERE id = '1'
Only the age field has changed. How can I determine this?
You cannot directly get the updated columns from the query result.
It can be get from some php query. Firstly we will have to select the row from database which we are going to update in a array variable. Than run the update query for the same row.
Lastly get the same row from database from select query in the new array variable.
Finally we get two arrays.
We can get the updated column with the array_diff_assoc php function.
See the below code for the same.
$sql = "SELECT * from mytable where id=1 limit 1";
$prev = mysqli_fetch_assoc(mysqli_query($conn, $sql));
//Get the column data in the array. Before update.
$sql = "UPDATE mytable SET name = 'Woton', age = '20' WHERE id = '1'";
$conn->query($sql);
// Update data
$sql = "SELECT * from mytable where id=1 limit 1";
$updated = mysqli_fetch_assoc(mysqli_query($conn, $sql));
// Again run the select command to get updated data.
$UpdatedColumns=array_diff_assoc($updated,$prev);
In a different note: If QueryLog has been enabled in the DB then you (or your script in PHP or Python or any) can easily see/read which part of the content has been updated and even you can monitor the DB.
The good news is, even you can target which table, which query etc.

How can I use mysqli / php to update all records after a query has already been executed?

I have a user form that sets a single record "current". No more than one record can be set to current at a time. So, I present the user a single drop down list, they choose the item they want to set current and hit "UPDATE" at the bottom of the form.
The PHP/Mysqli needs to go in and set all records column "current" to a value of 0 then update the one from the form to a value of "1".
Initially, I just did a simple count the number of rows, and run a bunch of queries to update the column to 0 or 1 if the loop counter = the id of the row. Well... that broke quick as I started doing testing on other portions and the index numbers got higher than the total number of rows. Yes, dumb way to do it initially!
Here's what I tried to do with the PHP / MySQL code:
// $link is the database link defined elsewhere. This does work as I use it all over the place
$setCurrent = X; // This is the number passed from my form
$init_query = "SELECT id, current FROM myTable";
if ($stmt = $link->$prepare($init_query) {
$stmt->execute() or die ($stmt->error);
$stmt ->bind_result($id, $current)
while ($stmt->fetch()){
if ($id == $setCurrent){
$update_sql = "UPDATE myTable SET current ='1' WHERE id='".$setCurrent."'";
$stmt2 = $link->prepare($update_sql);
$stmt2->execute;
}
else {
$update_sql = "UPDATE myTable SET current ='0' WHERE id='".$id."'";
$stmt2 = $link->prepare($update_sql);
$stmt2->execute;
}
$stmt->close();
This fails and gives me a Fatal error: Uncaught Error: Call to a member function execute on boolean in .....
I am racking my brain over this and can't figure out what the heck is going on. Its been a few years since I have worked in PHP/MySql and this is my first forray into OO Mysqli. Please be gentle :)
You're missing two closing curly braces. One for the first if() and the other for while()
why do them one at a time? You can do it in one query
$setCurrent = X;
$query = 'UPDATE myTable
SET `current` = (id = :current)';
$stmt = $link->prepare($query);
$stmt->bindValue(':current', $setCurrent);
$stmt->execute();
(and misusing the fact that if id equals $setCurrent, the part between ( ) resolves to true, which is 1.)
some explaining:
SELECT 10=10; would give a kind of "TRUE". But as Mysql does not give true, it give 1.
the same goes for:
SELECT 10=20; This is FALSE, so gives you 0.
Now back to your query: you want to get a value 0 for all record for which id not equal to some-number. And you want 1 when equal:
So you have to compare the column id's value to $setCurrent. When they match you get 1 and you put that 1 into the column "current"
And when they don't match, all other cases, then you get a 0 and that 0 goes into the column Current.
And yes, this could also be done as:
UPDATE mytable
SET `current` = CASE id
WHEN $setCurrent THEN 1
ELSE 0
END CASE
or using IF,
But they other syntax is way shorter
edit
backtics are needed around column name, as current is a reserved word

Can I count rows and get a column value at the same time with SQL?

I'm using a SELECT COUNT(*) in order to verify that a user exists with PHP PDO and MySQL. I'd also like to get a specific column value. There is only ever one value/row or no value/row per user.
I'm trying to do something like this:
$stmt = $link->prepare('SELECT COUNT(*) AND column FROM table WHERE user=:user');
What I'm hoping to get back is, 1, and the column value. Where I can then bind the column value to a variable.
If not, I'll have to first do the SELECT COUNT(*) then do another query to get the column name after verifying that the user and this column exists from the SELECT COUNT(*) query.
You just need to think a little.
"count(*)" is not a special method "to verify that a user exists". It's just a query where you select count because you just have no idea what to select else.
But as long as you have a column to select, you don't need no counts anymore.
Therefore, just select your value, and as long as you are getting it, you can tell that a user exists
$stmt = $link->prepare('SELECT column FROM table WHERE user=:user');
$stmt->execute([$user]);
$col = $stmt->fetchColumn();
if ($col) {
// user exists
$something = $col; // use $col as you wanted
}
While selecting count() and a column without a group by operator is a tricky query, and you should avoid it in general.
SELECT count(*), column FROM table where user=:user
It's what you want no ?
Otherwise you can count the number of result in php
$pdo = new PDO('mysql:host=XXX.fr.mysql;dbname=YYYY', 'ZZZ', 'TTT', $pdo_options);
$response = $pdo->query('SELECT column FROM table');
$count = 0;
while ($data = $response->fetch())
{
$count++;
}
$reponse->closeCursor();

Update the first row mysql php

I'm trying to update my first row in my database. I use the Limit 1 to only update the first row but nothing is happening. There are definitely matching rows but nothing changes in the database.
Here is the code:
foreach ($player_fromsite as $match_player_in_game) {
//$querytwo = 'INSERT INTO `'.$tablename.'` '.' (`'.$match_player_in_game.'`) '.'VALUES'.'("' . 'yes' . '")';
$querytwo = 'UPDATE '.$tablename.' SET `'.$match_player_in_game.'` = "'.'yes'.'" WHERE `'.$match_player_in_game.'` = "'.'NULL'.'" LIMIT 1';
$querythree = 'UPDATE '.$tablename.' SET `'.$match_player_in_game.'` = "'.'yes'.'" WHERE `'.$match_player_in_game.'` = "'.'NULL'.'" LIMIT 1';
for($a=0;$a<11;$a++){
if($match_player_in_game == $home_players[$a]){
// Insert a row of information into the table "example"
mysql_query($querytwo) or die(mysql_error());
}else{
mysql_query($querythree) or die(mysql_error());
}
}
}
Is the query correct?
In MySQL use IS NULL to compare with NULL.
For example: "UPDATE table SET field = 'yes' WHERE field IS NULL"
NULL isn't a string, so you shouldn't be using = 'NULL', unless you actually set it to that string value. Use IS NULL instead.
You need to define "first row". First row based on an autoincrementing id value? First based on a timestamp date? You need to specify this as MySQL has no concept of "first row".
For example, if you do something like this in MySQL:
SELECT * FROM table LIMIT 1
You are not guaranteed to get the same record back each time.
Most likely you will need to specify an ORDER BY condition on a key column, as without it, you have no guarantee of which row your LIMIT 1 will apply to. I really can't think of a case where one might use LIMIT without an ORDER BY clause, as the two really go hand in hand.
So your query should look like:
UPDATE table
SET field = 'yes'
WHERE field IS NULL
ORDER BY some_key_field ASC
LIMIT 1
Note that even this query would not update the same row every time. It would update the first record (as specified by ORDER BY) that has a NULL value for the specified field. So if you ran this query 10 times, it would change 10 different records (assuming there are that many records with NULL values).

Setting status of other rows after INSERT

Hey, I have a field called STATUS and it is either 1 to show or 0 to hide. My code is below. I am using an edit in place editor with jQuery. Everytime you update it creates a new ROW which I want, but I want only the new one to have STATUS = 1 and the others to 0. Any ideas on how I would do that?
<?php
include "../../inc/config.inc.php";
$temp = explode("_", $_REQUEST['element_id'] );
$field = $temp[0];
$id = $temp[1];
$textboxval = stripslashes(mysql_real_escape_string(preg_replace('/[\$]/',"",$_REQUEST["update_value"])));
$query = "INSERT INTO notes ($field,status,date,c_id) VALUES ('$textboxval','1',NOW(),'$id')";
mysql_query($query);
echo($_REQUEST['update_value']);
?>
I am not sure exactly what you mean - do you want to make all the entries except the new one have status = 0? If so, just issue an update before the insert:
UPDATE notes SET status = 0
However, I should also note that you have a potential SQL injection to worry about. By stripping slashes after applying "mysql real escape string", you are potentially allowing someone to put text in your SQL statement that will execute an arbitrary SQL statement.
Something like this, sorry for the post before, I mis read it the first time then went back:
<?php
include "../../inc/config.inc.php";
$temp = explode("_", $_REQUEST['element_id'] );
$field = $temp[0];
$id = $temp[1];
$textboxval = mysql_real_escape_stringstripslashes((preg_replace('/[\$]/',"",$_REQUEST["update_value"])));
// set older entries to 0 - to not show but show in history
$hide_notes = "UPDATE notes SET status = 0";
mysql_query($hide_notes);
// add new entry with status of 1 to show only latest note
$query = "INSERT INTO notes ($field,status,date,c_id) VALUES ('$textboxval','1',NOW(),'$id')";
mysql_query($query);
echo($_REQUEST['update_value']);
?>
i just ran in to a problem I didn't of the set up of my table doesn't allow me to show more than one client a time and i will be having numerous clients, my bad on planning ha
You really want to get the ID of the newly generated row and then trigger an UPDATE where you all rows where the ID is not the new row, e.g.
UPDATE notes SET status = 0 WHERE id != $newly_generated_id
If the ID column in your table is using AUTO_INCREMENT you can get its ID via "SELECT LAST_INSERT_ID()" and then use the return value in that statement in your UPDATE statement.
Pseudo code:
$insert = mysql_query("INSERT INTO ...");
$last_id = mysql_query("SELECT LAST_INSERT_ID()");
$update = mysql_quqery("UPDATE notes SET status = 0 WHERE id != $last_id");
The only caveat to this approach is where you might have a brief moment in time where 2 rows have status=1 (the time between your INSERT and the UPDATE). I would wrap all of this in a transaction to make the whole unit more atomic.

Categories