Reputation: 4326
There is a table with an int field - field_1.
I want to insert a new row.
The field_1 value will be Maximum value from all the entries plus one.
I've tried:
INSERT INTO table (field names, `field_1`)
VALUES (values, '(SELECT MAX(field_1) FROM table)');
I get '0' in the field_1.
I know I can do it in separate queries.
Is there a way to perform this action with one query? I mean one call from php.
I have an auto-increment field 'id' and I want to add 'position' field. I want to be able to make changes in position but the new item will always have highest position
Upvotes: 6
Views: 11798
Reputation: 1265
Try this:
INSERT INTO table (some_random_field, field_to_increment)
SELECT 'some_random_value', IF(MAX(field_to_increment) IS NULL, 1, MAX(field_to_increment) + 1)
FROM table;
Or this:
INSERT `table`
SET
some_random_field = 'some_random_value',
field_to_increment = (SELECT IF(MAX(field_to_increment) IS NULL, 1, MAX(field_to_increment) + 1) FROM table t);
P.S. I know it's 4 years late but I was looking for the same answer. :)
Upvotes: 4
Reputation: 61969
Whatever it is that you are trying to do, it will not work, because it is not guaranteed to be atomic. So two instances of this query executing in parallel are guaranteed to mess each other up at some random point in time, resulting in skipped numbers and duplicate numbers.
The reason why databases offer auto-increment is precisely so as to solve this problem, by guaranteeing atomicity in the generation of these incremented values.
(Finally, 'Auto Increment Manually' is an oxymoron. It is either going to be 'Auto Increment', or it is going to be 'Manual Increment'. Just being a smart ass here.)
EDIT (after OP's edit)
One inefficient way to solve your problem would be to leave the Position
field zero or NULL, and then execute UPDATE table SET Position = Id WHERE Position IS NULL
. (Assuming Id
is the autonumber field in your table.)
An efficient but cumbersome way would be to leave the Position
field NULL when you have not modified it, and give it a value only when you decide to modify it. Then, every time you want to read the Position
field, use a CASE
statement: if the Position
field is NULL, then use the value of Id
; otherwise, use the value of Position
.
EDIT2 (after considering OP's explanation in the comments)
If you only have 30 rows I do not see why you are even trying to keep the order right on the database. Just load all rows in an array, programmatically assign incrementing values to any Position
fields that are found to be NULL, and when the order of the rows in your array changes, just fix the Position
values and update all 30 rows in the database.
Upvotes: 9
Reputation: 19027
ALTER TABLE table_name AUTO_INCREMENT = 1 allows the database to reset the AUTO_INCREMENT to:
MAX(auto_increment_column)+1
It does not reset it to 1.
This prevents any duplication of AUTO_INCREMENT values. Also, since AUTO_INCREMENT values are either primary/unique, duplication would never happen anyway. The method to do this is available for a reason. It will not alter any database records; simply the internal counter so that it points to the max value available. As stated earlier by someone, don't try to outsmart the database... just let it handle it. It handles the resetting of AUTO_INCREMENT very well. See gotphp
Upvotes: 1