Hi I'm trying to select the last ID in my table then add 1 to the value. I am selecting the last row just find the problem is that I'm having problems with the +1 I think this is because it's an array but I'm not sure.
$result = mysql_query("SELECT `id` FROM `users` ORDER BY `id` DESC LIMIT 1");
$row = mysql_fetch_row($result);
$pin = $row[0]+1;
echo ($row[0]); //returns the id
echo ($pin); // returns null
Any thoughts on this would be great.
Try this:
SELECT max(id) + 1 from users
But if you are doing an insert, just grab mysql_last_insert_id() to find out what was just inserted. Otherwise you will have issues with concurrency.
Your id is setup as AUTOINCREMENT correct? You should never never never never ever assign the primary key yourself. this is the db servers job.
You should use mysql_insert_id().
printf("Last inserted record has id %d\n", mysql_insert_id());
That will display the most recently inserted id.
There are several possible solutions. The easiest given the code you already have above may be:
$pin = intval($row[0])+1;
That said, there are definite improvements/optimizations to be made in the code that other answers here touch on. But if you're looking for the shortest path from what you have to what you want, that one change might be it.
You can not reliably determine the next inserted id before the actual insert takes place. The last record may have been deleted, but that does not change the auto_increment value of the table. Also, if two (or more) concurrent requests happen, both can check the last inserted id and find the same value. When inserting the rows, both will get different ids...
Related
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.
I have the following call to my database to retrieve the last row ID from an AUTO_INCREMENT column, which I use to find the next row ID:
$result = $mysqli->query("SELECT articleid FROM article WHERE articleid=(SELECT MAX(articleid) FROM article)");
$row = $result->fetch_assoc();
$last_article_id = $row["articleid"];
$last_article_id = $last_article_id + 1;
$result->close();
I then use $last_article_id as part of a filename system.
This is working perfectly....until I delete a row meaning the call retrieves an ID further down the order than the one I want.
A example would be:
ID
0
1
2
3
4-(deleted row)
5-(deleted row)
6-(next ID to be used for INSERT call)
I'd like the filename to be something like 6-0.jpg, however the filename ends up being 4-0.jpg as it targets ID 3 + 1 etc...etc...
Any thoughts on how I get the next MySQL row ID when any number of previous rows have been deleted??
You are making a significant error by trying to predict the next auto-increment value. You do not have a choice, if you want your system to scale... you have to either insert the row first, or rename the file later.
This is a classic oversight I see developers make -- you are coding this as if there would only ever be a single user on your site. It is extremely likely that at some point two articles will be created at almost the same time. Both queries will "predict" the same id, both will use the same filename, and one of the files will disappear, one of the table entries may point to the wrong file, and the other entry will reference a file that does not exist. And you'll be scratching your head asking "how did this happen?!"
Predicting auto-increment values is bad practice. Don't do it. Plan for concurrency.
Also, the information_schema tables are not really tables... they are server internals exposed to the SQL interface. Calls to the "tables" table, and show table status are expensive calls that you do not want to make in production... so don't be tempted to use something you find there.
You can use mysql_insert_id() after you insert the new row to retrieve the new key:
$mysqli->query($yourQueryHere);
$newId = $mysqli->insert_id();
That requires the id field to be a primary key, though (I believe).
As for the filename, you could store it in a variable, then do the query, then change the name and then write the file.
I'm working on a portal / large website and I have a question as to how to optimise my mySql / PDO queries in a special case.
I developed it this way : when I'm inserting an iD (unique / primary) I do the following code to find out the highest unused id in a specific table, and then do an INSERT with that id ($next_avail).
After a short chat last days on stackoverflow I got the ideea that AUTO_INCREMENT is best for this action.
But now, I realize that in most of the cases I also use $next_avail (the value of the AUTO_INCREMENT how it would be) to insert in other tables as a column, as well.
So my code makes sense for these inserts.
My question is, how would this code below work for millions of rows as speed, for each insert I do depends on it.
Please write comments and ask me to clarify what is not clear for you, in this question.
Thanks, Adrian
$next_avail = 1 ;
$stmt = $db->prepare("SELECT news_id from mya_news ORDER BY news_id DESC LIMIT 1");
$stmt->execute();
while ( list($id) = $stmt->fetch(PDO::FETCH_BOTH) ) {
$next_avail = $id + 1;
}
You don't need to do that, just use an auto_increment in your table, and also use the PHP functions to get the last_inserted_id mysql_insert_id()
take a look to this sites:
http://php.net/manual/en/function.mysql-insert-id.php
this one is with PDO
http://php.net/manual/en/pdo.lastinsertid.php
Possibly use max rather than ordering the results and using a limit.
However this is very risky. A chance that 2 bits of processing will both get the same $next_avail at the same time. I would suggest changing the order you insert rows (or even inserting a dummy row to get the next id, and updating the row later on) to use the AUTO_INCREMENT column value
I have a form that lets users create new records,
In the field that is the id that auto-increments i want the user to see the record number that this record is by somehow showing latest value+1 in the fields value.
I was thinking of something like:
<input type="text" value="<?php echo $myQuery['recordId'].length+1"/>
But that doesn't work.
Again, this is only to get the default value in the <input>
Instead of having to look up the last id, And this form is only used by one admin.
You can find the one plus the highest id by selecting it:
SELECT MAX(id)+1 FROM table
But like David said, you're not guaranteed this will be the id that is used, because 2 people could load the page at about the same time.
To get the last id relevant to that connection, use mysql_insert_id
In your case you'll have to insert an empty record in the db before you can guarantee that it will count. It will leave a lot of empty records if the users don't proceed, but you can do a cleanup every time the form is loaded by deleting records created more than one hour ago that don't have a title value or something like that.
if you absolutely need it to be an integer, you can always create a special table with only one auto_increment column, insert to it, get the last_insert_id() and use that. this is kind of mimicking the sequences in oracle. the ids that dont get used will go waste, but the other problems associated with multiuser scenarios will not occur. The following code copied from mysql documentation on information functions. Go there to read on the promises of this code.
CREATE TABLE sequence (id INT NOT NULL);
INSERT INTO sequence VALUES (0);
UPDATE sequence SET id=LAST_INSERT_ID(id+1);
SELECT LAST_INSERT_ID();
Now back to my own words. If it does not have to be an integer you can use guid. There is a uniqid function in php, and there is a uuid function in mysql. the theory says even if everyone keeps generating guids independently all the time, every guid will be unique.
So this is one way of doing it:
<?php
$query = "select uuid()";
$result = mysql_query($query);
$row = mysql_fetch_row($result);
$uuid = $row[0];
?>
<input type="text" value="<?php echo $uuid; ?>"/>
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.