Thanks for asking me to make my question clearer.
I have a form which is used to save content in a database.
The user is also allowed to update any content by editing the fields in the form and submitting it.
The update query looks something like this:-
$res = mysql_query("UPDATE freight SET .... WHERE id='$id'") or die ( mysql_error());
if(mysql_affected_rows() > 0){
//do some stuff
return true;
}
else{
return false;
}
Now my problem is this: If the user changes some field while updating the form, mysql_affected_rows() is > 0 so I am able to "//do some stuff".
But if the user does not change any field in the form and simply submits, mysql_affected_rows return 0 and I reach the false block.
I was under the impression that UPDATE should overwrite every time thereby mysql_affected_rows() should return 1 irrespective of whether any fields have been changed or not.
I use the return value to display an appropriate success or error message in the screen. Hence this is a serious bug.
Can you suggest whats the right way to achieve the correct functionality?
Thanks,
Vish
mysql_affected rows() -1 will be returned if the query itself can not be issued to the server, possibly because of syntax error AND if the last query was not either an INSERT or UPDATE statement.
When using UPDATE, MySQL will not update columns where the new value
is the same as the old value. This creates the possibility that
mysql_affected_rows() may not actually equal the number of rows
matched, only the number of rows that were literally affected by the
query.
so your solution can be achieved by below logic ( but this is not safe)
if(mysql_affected_rows()!=-1){
}
if( $_POST['message'] != '' ) {
// add the field to your query
} else { // this is optional
// don't add it to your query
}
// do the mysql update here
Related
I have a MySQL stored procedure that updates data across a set of tables (basically for one record in the principal table and related records in a set of child tables). It's called via AJAX through a PHP function. (That is, the AJAX call is to a PHP page, which ultimately calls this SP.) It was working fine, but now I'm trying to make it do one more thing and running into the "Commands out of sync; you can't run this command now" error.
The change is to store one more item in the principal table, but to do so may require adding an item to a child table (called ActionTopic). The page lets the user either choose from a dropdown or type in a new value. I've added two parameters to the SP: one is the PK chosen in the dropdown, the other is the new value typed in. In the SP, I've added the code below. It checks whether there was a new value typed in. If so, it calls another SP that checks whether the value typed in is already in the table and, if not, adds it. (I've tried with the code to check and add the record inline rather than in a separate SP and I have the same problem.)
if cNewTopic <> '' then
-- First, make sure the new topic isn't already there
call aoctest.AddActionTopic(cNewTopic);
-- SELECT #iTopicID := iID FROM ActionTopic WHERE UPPER(Description) = UPPER(cNewTopic);
SET #iTopicID = LAST_INSERT_ID();
else
SET #iTopicID = Topic;
end if;
The page works if the user makes a choice from the dropdown. The problem only occurs when the user types in a new value. Even when I get the error, everything else works as expected. The new value is added to the child table, and the parent table and other children are updated as expected.
Interestingly, if I call the SP in MySQL Workbench with the same parameters (after ensuring that the new value isn't in the new table), it runs without error. The only odd thing I've noticed is that I get two rows in the Output section of MySQL Workbench rather than one. Both show the call to the SP. The first shows "1 row(s) returned" and a period of time, while the second shows "0 row(s) returned" and "-/0.000 sec". A call to the SP in MySQL Workbench where the new value is already in the table also shows two rows in the Output section, but the second one shows "1 row(s) returned".
Not sure whether any of the other code is needed here. If you think I need to show more, please ask.
UPDATE: Based on the comment from Pete Dishman, I took a harder look at where the error is occurring. It's not the original SP call giving an error. It's the next call to MySQL, which is still inside the Ajax call.
The code processing the result already had this code:
//not sure why next line should be needed.
mysqli_next_result($conn);
I tried both simply doubling the call to mysqli_next_result (that is, two in a row) and putting it into a loop along the lines Pete suggested. With two calls, I still get the same error. With a loop, I wait 30 seconds and then get error 500: Internal server error.
UPDATE 2: I tried with a loop for mysqli_more_results() (similar to the one in Pete Dishman's reply) and echoing a counter inside the loop. The code brought my internet connection to a crawl and I finally had to break out of it, but there were dozens of iterations of the loop. Just tried the following:
mysqli_free_result($result);
$result = mysqli_store_result($conn);
mysqli_free_result($result);
if (mysqli_more_results($conn)) {
$result = mysqli_store_result($conn);
mysqli_free_result($result);
}
$allresult = getsubmissions($conn);
Found a noticeable delay before it failed.
Even if you can't tell me what's wrong, I'd appreciate ideas for how to debug this.
This may be because the stored procedure is returning multiple result sets (the two rows in workbench).
When querying from php you need to retrieve both result sets before you can send another query, otherwise you get the "commands out of sync" error.
The documentation seems to imply this is only the case when using mysqli_multi_query but we have it in our code when using mysqli_real_query.
Our query code is along the lines of:
mysqli_real_query($conn, $sql);
$resultSet = mysqli_store_result($conn);
while (!is_null($row = mysqli_fetch_array($resultSet, MYSQLI_BOTH)))
{
$results[] = $row;
}
mysqli_free_result($resultSet);
// Check for any more results
while (mysqli_more_results($conn))
{
if (mysqli_next_result($conn))
{
$result = mysqli_store_result($conn);
if ($result !== FALSE)
{
mysqli_free_result($result);
}
}
}
return $results;
The code would be different obviously if you're using PDO, but the same principle may apply (See http://php.net/manual/en/pdostatement.nextrowset.php)
I've solved my own problem by reworking the code that processes the result as follows:
if (mysqli_more_results($conn)) {
mysqli_free_result($result);
mysqli_next_result($conn);
$result = mysqli_store_result($conn);
mysqli_free_result($result);
if (mysqli_more_results($conn)) {
mysqli_next_result($conn);
$result = mysqli_store_result($conn);
if (!is_null($result) and gettype($result)!== 'boolean') {
mysqli_free_result($result);
}
}
}
$allresult = getsubmissions($conn);
I know it is a frequently asked question, but let me explain a bit why I need to ask that again.
Most answers out there suggests using
$this->db->affected_rows()
This is not working in my situation as I may have situation that the update data is the same as the data in the database, so it will return 0 even if the update is success.
I know I can write another query to check if it is because the data are the same, but this sounds stupid to me.
Another way is to use the Active Record Class in code igniter, so the line will be something like:
$error_num = $this->db->update("users", array('firstName' => $newFirstName));
return $error_num;
which is a better solution (at least it works even if there is no update due to repeated data). However, I would like to use the database class, i.e. something like:
$this->db->query('update table set field = somedata where id=1');
It increases the readability of my code to coder who knows php + SQL but are not familiar with code igniter, but then this is why I am asking if anybody knows how do I get the error number if I query in this way?
i.e. Something like mysql_errno() when using mysql_query($query) in PHP.
Both will work like same only difference
if you using active record class all the input variables are escaped automatically
If you want security you better to go with active record class
If you use normal query execution you have to escape the input parameters manually using $this->db->escape_str()
$id = $this->db->escape_str($id)
You can check the query execution status.
$status = $this->db->update("users", array('firstName' => $newFirstName));
if($status)
{
//here you can check the number of affected rows if required
echo $this->db->affected_rows();
}else{
//here you can prcess for failure case
log_message('Error', $this->db->_error_message());
}
//return the status to required place
return $status
I have use this code for checking.
$status = $this->db->query('update table set field = somedata where id=1');
if($status)
return true;
else
return false;
I'm having problems with a piece of code and wonder if someone can help.
I have a form that submits information to a MySQL database, I have the correct code for checking to see if the submitted product code already exists, and if so shows a warning message and the record is not added.
That code is:
$result = mysql_query("SELECT * FROM listing_1 WHERE product_code='$product_code'");
$num_rows = mysql_num_rows($result);
if ($num_rows) {
adminwarnmessage("DUPLICATE REFERENCE CODE","FAILURE - <b>$product_name</b> has <b>NOT</b> been added because the reference number already exists.");
}
That works fine for Data Entry, however I have another form that allows users to edit the record, this is what is causing me a problem, as the above code only tells me that there is already a matching record in the database, Of course when I try to save (update) the record it now tells me I can't because it is a duplicate.
What I would like to happen is that it doesn't allow users to choose another productcode that already exists, but I want them to be able to update the record using the same product code the form fetched from the database.
Hope that makes sense, any help greatly appreciated.
If you have id (primary key) then You will have to compare with id of that product before updating the record. For example
$result = mysql_query("SELECT * FROM listing_1 WHERE product_code='$product_code' AND id!=$id");
$num_rows = mysql_num_rows($result);
if ($num_rows) {
echo "duplicate record";
}
Here $id is the id of the product that you should have while editing the record.
following is the step you need to follow when you managing the Database
First you need an primary key(auto_increment) in "ID" field
When you execute insert query that time first check where record is already available or not. if not available than only you should execute insert query.
use primary key filed for update, delete etc...
if you follow the above step than you never face this problem
Are you perhaps checking for duplicate occurrences in both of insert and update statement? If so, you shouldn't. Duplicate entry is relevant only when "inserting". You shouldn't use the same check for update. Hope that helps.
why the same code for update also? you can use another query for updating which is better for debugging if you have problems later. try this
$result = mysql_query("UPDATE listing_1 SET product_code='$new_product_code' WHERE product_code='$product_code' AND id='$id'");
if($result) {
echo "your product was updated.";
} else {
echo "your product is not in DB";
}
EDIT: be careful in updating or inserting things, take always id to check unless your product_code is unique
EDIT
I have resolved this issue by making $productcode field a unique Index.
Now when editing if there is a duplicate..
Mysql does not accept the update query, it returns an error code
I trap that error code and include it in an if statement...
if( mysql_errno() == '1062' )
adminwarnmessage("DUPLICATE REFERENCE CODE","FAILURE - $product_name has NOT been added because the reference number already exists");
}
adminmessage("Item Updated", Congratulations you updated $productname succesfully");
}
This now allows editing of $productcode but does not allow it to be changed to one already used in the database.
Thank you to everyone who took the time to offer help
I have a question for you.
I am creating an administration panel, this is the first time for me, and I have some problems.
1. Problem
I am using mysqli_fetch_assoc() in this way:
$row_cnt = mysqli_fetch_assoc($result);
printf('Result set has %d rows.<br />', $row_cnt);
if ($row_cnt['COUNT(id)'] == 0) {
return false;
} else {
return true;
}
I use this to see if in the DB there are some entries, it returns 1 everytime, whatever thing I insert in the fields. I thought that it has to return 0 if there are no entry in the DB, am I wrong?
Please be patient, this is my first login page with admin panel.
Just from taking a quick peek -
mysql_real_escape_string requires a connection to be established via mysql_connect, you need to use the mysqli_real_escape... function - http://php.net/manual/en/mysqli.real-escape-string.php
You don't specify what SQL you are actually using, but assuming it is something similar to
Select Count(*) from mytable where myvalue= 'Something'
The RowCount will always be one 1 as The Count will always be returned.
I have a bit of an issue with my code.
I'm making an administrative panel for users to add things to the database. On occasion, they might try to save data without changing it (open a dialog, click save without changing anything). This, of course, will make mysql_affected_rows() return '0' when checking to see if the UPDATE query worked.
Is there another query to make that will always UPDATE regardless of whether the data is the same or not (or can I modify a simple UPDATE query to always update)?
EDIT
This is for users who don't have programming experience. Of course you wouldn't want to update if there's no reason to, but when a user tries to update and it doesn't happen I end up showing a failure message. Rather than there being something wrong, its just it doesn't need to be updated. I need a way to show the user that, instead of a generic 'failure' message. If it failed for another reason, I still need to know.
From the MySQL Documentation:
If you set a column to the value it currently has, MySQL notices this
and does not update it.
Instead of checking mysql_affected_rows, just check to see if the query was successful:
if(!mysql_query("UPDATE ..."))
{
//failure
}
else
{
$verification = mysql_query("SELECT ROW_COUNT() as rows_affected");
$row = mysql_fetch_row($verification);
$rows_affected = $row[0];
if ($rows_affected > 0)
{
//update was performed
}
else
{
//no update was needed
}
}