Updating a field which the Select query loop is based on - php

This is a rough example of my mysql query (note: this is inside an other loop that goes through all users):
$query = db.query('SELECT * FROM table WHERE userid = $uid AND reminded = 0');
while ($row = $query->fetch()) {
// send personalized reminder email to the user
db.query('UPDATE table SET reminded = 1 WHERE userid = $uid');
}
The field reminded is set to 1 for all instances for that user.
My question is:
Is the query/while (fetch) already loaded into memory based on the original terms (reminded = 0), or will the remaining while loop behave according to those updates (reminded = 1)?
Let's say the user had 50 rows where reminded is 0, and the query selects those: Are they still existing with the value 0 in the rest of the while loop even though they were all changed to 1 during the loop?

Assuming that the code and SQL you have is only an example (because you should update directly without a php loop).
The fetch on the table rows is executed on the DB row by row.
So, if one or more of these rows are updated in the while loop, in next iterations you will retrive and update (again) the previous updated rows.
I think that you have to be careful "only" if you are updating a field that is part of an index or a field that is used in the SQL to retrieve data (es. a field used in the ORDER BY, etc.).

Related

Mysql only update if row has been inserted before

I want to only run the update query if row exists (and was inserted). I tried several different things but this could be a problem with how I am looping this. The insert which works ok and creates the record and the update should take the existing value and add it each time (10 exists + 15 added, 25 exists + 15 added, 40 exists... I tried this in the loop but it ran for every item in a list and was a huge number each time. Also the page is run each time when a link is clicked so user exits and comes back
while($store = $SQL->fetch_array($res_sh))
{
$pm_row = $SQL->query("SELECT * FROM `wishlist` WHERE shopping_id='".$store['id']."'");
$myprice = $store['shprice'];
$sql1 = "insert into posted (uid,price) Select '$uid','$myprice'
FROM posted WHERE NOT EXISTS (select * from `posted` WHERE `uid` = '$namearray[id]') LIMIT 1";
$query = mysqli_query($connection,$sql1);
}
$sql2 = "UPDATE posted SET `price` = price + '$myprice', WHERE shopping_id='".$_GET['id']."'";
$query = mysqli_query($connection,$sql2);
Utilizing mysqli_affected_rows on the insert query, verifying that it managed to insert, you can create a conditional for the update query.
However, if you're running an update immediately after an insert, one is led to believe it could be accomplished in the same go. In this case, with no context, you could just multiply $myprice by 2 before inserting - you may look into if you can avoid doing this.
Additionally, but somewhat more complex, you could utilize SQL Transactions for this, and make sure you are exactly referencing the row you would want to update. If the insert failed, your update would not happen.
Granted, if you referenced the inserted row perfectly for your update then the update will not happen anyway. For example, having a primary, auto-increment key on these rows, use mysqli_insert_id to get the last inserted ID, and updating the row with that ID. But then this methodology can break in a high volume system, or just a random race event, which leads us right back to single queries or transaction utilization.

Starting mysqli_fetch_array from a specific row

I have some records, which I use while($row = $result->fetch_assoc() to iterate on each one of them, then I get some other data from a different table using while($row2 = $result2->fetch_assoc(), that is, iterating also on each one of them, then displaying in a HTML table: part of first table data and part of second table data.
However, when I truncate the first table, and then insert new records, the second query $result2->fetch_assoc(), starts from the beginning of table and iterates X times, which is basically numbers of rows from first table. This is not what I want, I want to remember the last place of iteration from its table (table 2), then, when called again, only iterate the remain rows in the second table, always which is dependent on nth times from first table.
I found an answer in stackoverflow, which you can find it here, however, I didn't understand it correctly: how can you save last LIMIT value, so to start from X id if the $result2->fetch_assoc()is called again?
I thought about storing a counter in a text document (which is incremented by first while loop), then use LIMIT from that certain number, but I don't really get how to get it work.
Edit: here are some additional info:
Table "aplikimet" schema:
Table "aplikimet_2" schema:
$sql = "SELECT id, emri, mbiemri, email, telefoni, vendbanimi, datelindja, mesazhi FROM aplikimet";
$sql2 = "SELECT statusi, uid FROM aplikimet_2";
$result = $conn->query($sql);
$result2 = $conn->query($sql2);
if (($result->num_rows > 0) AND ($result2->num_rows>0)){
(html table and th are here)
while((($row = $result->fetch_assoc()) AND $row2 = $result2->fetch_assoc()){
(html td are here)
Thanks for your help!
every time you call fetch_assoc() an internal pointer is incremented.
after last element the call returns false so your while(...) loop will end.
to reset it you can call
mysqli_data_seek($result, 0);
or
$result->data_seek(0);
see here
IMHO is not a great way to do it.
If you want to loop multiple times the same rowset you can save it in an array after the first complete loop. Then loop with foreach() your array all the times you need (your connection can be already closed at that time)
To limit the number of the rows returned by your query use the SQL LIMIT clause which can have different syntax depending on RDBMS you are using.

mysql unique index from set of columns

I am creating an application that inserts (or updates) values in mysql daily. A simplified recordset with headers is :
ItemName,ItemNumber,ItemQty,Date
test1,1,5,2016/01/01
test1,1,3,2016/01/02
test2,2,7,2016/01/01
test2,2,5,2016/01/02
When using a simple insert statement for the above recordset with 16 columns and 216.000 records takes about 4 minutes (php/mysql) - This covers a week of values. Of course if I import the same recordset I get duplicates. I am trying to find a way to effectively disallow duplicate entries.
The aim is to : In the scenario where I import every day a recordset that has dates for the current week I end up with the addition of the new dates only.
The only thing that might change in consecutive imports is the ItemQty.
In php I made a logic where I query the db for ItemName,ItemNumber,Date with the values I am trying to insert. If there is a result on the SELECT statement, I break. If there isn't, I proceed inserting a new row.
Problem is that with the addition of this logic now it does not take 4 minutes, but a couple of hours. (Works though)
Any ideas?
I was thinking perhaps when I insert, to insert something like a checksum column, for example md5(ItemName,ItemNumber,ItemQty,Date) and then check this checksum rather than SELECT * FROM $table WHERE ItemName = value ,ItemNumber = value,ItemQty = value,Date = value that I currently have.
My problem is that the records I insert have nothing unique basically. Uniqueness comes from a group of fields only if compared to the dataset to be imported. If I manage somehow to get uniqueness, I'll solve my other problem too, which is deleting a row or updating a row when the ItemQty changes.
The one that you are looking for is the unique constraint. Using unique constraint, you can add all your columns to the constraint and if all columns satisfied the inserting data, it will not proceed in inserting
Few options:
1) On PHP, iterate over the records, mapping the duplicate ones and keeping the newests
$itemsArray = []; // The array where you have stored your data
$uniqueItems = [];
foreach($itemsArray as $item)
{
if(isset($uniqueItems[$item['ItemName']]))
{
$oldRecord = $uniqueItems[$item['ItemName']];
$newTimeStamp = strtotime($item['Date']); // Might not work with your format date
$currentTimeStamp = strtotiem($oldRecord['Date']);
if($newTimeStamp > $currentTimeStamp)
{
$uniqueItems[$item['ItemName']] = $item;
}
}
else
{
$uniqueItems[$item['ItemName']] = $item;
}
}
// uniqueItems now hold only 1 record per ItemName (the newest one)
2) Sort the data in php by date on ascending order(before inserting in database). Then, on your clause, use ON DUPLICATE KEY UPDATE. This will cause mysql to update the records with duplicate key. In this case, the older records will be inserted first, so the lastest records will be inserted last, overwritting the old records data.

Jquery - finding range between two unique id's in mysql

Another question which has me perplexed:
I have a table which enables users to enter as many rows as they like based on their userid and unique id (auto incremental).
I need to be able to get this information from mysql and place the previously entered information into the fields on the web application (they may need to be edited before confirming that they're correct).
I store the total number of records for that user so far in one variable, and the total number of records for all users in another variable.
The question is: how do I get the range of ids for the records the user has already enterered.
Example: User 1 has 2 records in the database and there is 7 in total (5 by another user). How would I get the unique IDs of the 2 records that already exist?
Thanks for any suggestions you may have!
I'm not entirely sure what you mean, so this may or may not be helpful.
This SQL should give you the record ids:
SELECT id FROM tableofuserrows WHERE userid = [User Id]
You can then fetch this from the database with PHP, e.g.
$q = mysql_query('SELECT id FROM tableofuserrows WHERE userid = ' . (int) $_GET['userid']) or die(mysql_error());
$result = array();
while ($row = mysql_fetch_assoc($q)) {
$result[] = $row['id'];
}
mysql_free_result($q);
echo json_encode($result);
So if you wanted to fetch these IDs from the browser using jQuery:
$.getJSON("http://url", { userid: 3 }, //set userid properly
function(data){
$.each(data, function(i,id){
//do something with the recordid
alert(id);
});
}
);
Do you have to do this dynamically using jquery or can you load the fields in the web form with the rest of the page using php ?
Either way, you're going to need to query the database table for all rows where userid = a certain user. Once you get these results, you'll need to create a page you can call and get results from using jquery if you're going that route.
Someone just posted what I'm saying with code examples :-)
I decided to use MIN(id) in the select statement, counting how many rows there are and then populating the form fields accordingly, starting with the min value and adding the counted rows. Works well ;)

MySQL query in PHP gives obvious wrong result

I'm using PHP and PHPMyAdmin to create a small profile site.
I'm giving members an ID number, based on which is the biggest number currently in the database, +1
I did 25 tests before I got the PHP script where I wanted it to be.
I then deleted those 25 entries using PHPMyAdmin.
But now, when my PHP code does this:
function getLatestID() {
$query = "SELECT max(member_id) FROM members";
$result = #mysql_query($query) or showError("unable to query database for user information");
if (!($record = mysql_fetch_array($result))) return null;
return $record[0];
}
I get the wrong number.
Test scenario: the database table holds 3 entries, with ID's 1, 2 and 3.
I start a debugging session and put a breakpoint on the return $record[0].
I check its contents and instead of 3, which is the biggest number, it's 28.
As in 25+3=28, the 25 entries that I allready deleted...
Does anybody know what's causing this and how I can fix it?
It's probably because you have auto_increment set and the query is returning the highest id. When you deleted the other records, you probably didn't reset the auto increment count.
If you're using auto_increment in MySQL then deleting records won't decrease the next value.
You can empty a table with TRUNCATE TABLE mytable - this will reset the value.
You can also change value that auto-increment thinks is the next value to allocate:
ALTER TABLE members AUTO_INCREMENT = 3;
Note that if you put in a value that is less than the current max value in the auto-increment column, it'll change the value to that MAX+1. To see what the current next value is set to, do this:
SHOW CREATE TABLE members;
At the end of the table definition, it'll show "AUTO_INCREMENT = 26" or whatever it's current value is.

Categories