I have a table with a column 'id' which has auto_increment on.
So for example when I add a new record it will assign it a number.
But what I need is a way I can change the order of the records so for example there are 48 records in the db and I want record 29 to have the id of 5 instead of 29. So is there a way for record 29 to replace 5 and for them to all move up one so 5 would now be record 6 etc?
Thanks!
If you need to allocate the id yourself, do not use an auto increment column.
A separate question is to do with renumbering records in a database table and yes, this can be done with an ordered update query.
First of all you would clear the space for the new record 5 thus:
UPDATE table SET id=id+1 WHERE id > 4 ORDER BY id DESC
Then you would renumber record 29 thus
UPDATE table SET id=5 WHERE id = 29
Related
I have a script which INSERT's data into a table and then later on when you INSERT new data it DELETE's the previous record/s and INSERT's the current data set.
The only issue is that the primary key gets wacked.
e.g. first four rows
1
2
3
4
then when i delete these and enter new data
5
3
4
6
note: the above numbers represent primary key id auto incrementations
Why does the incrementation become confused almost?
Auto-increment number do not get confused. They are unique over the table and that is the only purpose they have.
If you select the data then the DB will grab the records as fast as possible and if you do not specify a specific order then the records are returned in an unpredictable order.
That means if you specify
select * from your_table
order by id
Then the records have incrementing numbers. If you delete records then the gabs won't be filled.
If you want to restart the numbers, use truncate table instead of delete. This will reset the counter to 0:
truncate table <your table here>;
I wish to allow insertion of rows in the middle of a sql table and afterwards automaticly update the ascending id's to be +1.
Example:
ROW ID
1 5
2 6
3 7
4 8
I then want to be able to insert a 5th row with the id of 6, and make the other rows update to be +1 of their current number:
ROW ID
1 5
2 7
3 8
4 9
5 6
Is there an efficient way to this? other than running through the whole table and adjusting the other id's to +1?
Add an index to the ID column. That way you only need to run through the rows that are actually affected by the update operation instead of though the whole table. On the downside, each index makes inserts more expensive.
BTW Don't change ID entries if the ID column belongs to your primary key.
I have a table A which has a auto increment serial number field SLNO. When i insert values in table it will increment automatically like 1,2,3,4... etc. But when i delete a row from the table the order get break. ie, if delete row with serial number 2 then the serial number field will 1,3,4. But I want to maintain a continuous order like 1,2,3 even delete rows. Is there any way to maintain this order, like using trigger or somthing
A primary auto-increment key is only for uniquely identifying a record. Just leave it be.
Don't misuse the primary key as indicator of your record order. If you need specific order of your records then use an extra column for that. For instance a timestamp column.
If you need a specific order of your records use a timestamp column with a default value of current_timestamp. That way it will be inserted automatically.
ALTER TABLE your_table
ADD column inserted_timestamp TIMESTAMP default current_timestamp;
SQLFiddle demo
You should leave it as it is.
However, if you do really need, you can "recalculate" the primary key, the index:
set #pk:=0;
update
your_table
set pk=#pk:=#pk+1
order by pk;
add a column that will speicfy that is deleted
example:
1 - deleted already
0 - not deleted
and add where deleted = 0 in your select query
primary key column 2 column3 ..... deleted
1 1
2 0
3 0
4 1
5 0
Storing an number of a record would make deletes inefficient. Instead you can rely on existing SLNO indexes you already have, that should be enough for all use cases that come up to my mind.
If you SELECT whatever ORDER BY SLNO LIMIT ... OFFSET k, then returned rows have IDs k, k+1, k+2, ...
If you want to get an id of a record knowing its SLNO:
SELECT COUNT(SLNO) FROM A WHERE SLNO <= thatnumber
If you want to get thatnumber'th record:
SELECT * FROM A ORDER BY SLNO LIMIT 1 OFFSET thatnumber
You can do by alter the table and delete primary key then again create primary key.
But why you need this. If you have use this key as foreign key in other table. Then you lost all the data.
In my current application I am making a menu structure that can recursively create sub menu's with itself. However due to this I am finding it difficult to also allow some sort of reordering method. Most applications might just order by an "ordering" column, however in this case although doing that does not seem impossible, just a little harder.
What I want to do is use the ID column. So if I update id 10 to be id 1 then id 1 that was there previously becomes 2.
What I was thinking at a suggestion from a friend was to use cascades. However doing a little more research that does not seem to work as I was thinking it might.
So my question is, is there an ability to do this naively in MySQL? If so what way might I do that? And if not what would you suggest to come to the end result?
Columns:
id title alias icon parent
parents have a lower id then their children, to make sure the script creates the array to put the children inside. That part works, however If I want to use an ordering column I will have to make a numbering system that would ensure a child element is never higher then its parent in the results. Possible, but if I update a parent then I must uniquely update all its children as well, resulting in more MySQL queries that I would want.
I am no MySQL expert so this is why I brought up this question, I feel there might be a perfect solution to this that can allow the least overhead when it comes to the speed of the application.
Doing it on the ID column would be tough because you can't ever have 2 rows with the same ID so you can't set row 10 to row 1 until after you've set row 1 to row 2 but you can't set row 1 to row 2 until you set row 2 to row 3, etc. You'd have to delete row 10 and then do an update ID += 1 WHERE ID < 10... but you'd also have to tell MySQL to start from the highest number and go down....
You'd have to do it in separate queries like this:
Move ID 10 to ID 2
DELETE FROM table WHERE id = 10;
UPDATE table SET id = id + 1 WHERE id >= 2 AND id < 10 ORDER BY id DESC
INSERT INTO table (id, ...) VALUES (2, ...);
Another option, if you don't want to delete and reinsert would be to set the id for row 10 to be MAX(id) + 1 and then set it to 1 after
Also if you want to move row 2 to row 10 you'd have to subtract the id:
Move ID 2 to ID 10
DELETE FROM table WHERE id = 2;
UPDATE table SET id = id - 1 WHERE id > 2 AND id <= 10 ORDER BY id DESC
INSERT INTO table (id, ...) VALUES (10, ...);
If you don't have your ID column set as UNSIGNED you could make all the IDs you want to switch to negative ids since AUTO_INCREMENT doesn't do negative numbers. Still this is pretty hacky and I wouldn't recommend it. You also probably need to lock the table so no other writes happen while this is running.:
Move ID 2 to ID 10
UPDATE table SET id = id * -1 WHERE id > 2 AND id <= 10;
UPDATE table SET id = 10 WHERE id = 2;
UPDATE table SET id = id * -1 - 1 WHERE id < -2 AND id >= -10;
I'm using auto-increment to assign a id to every new entry in my database.
Also, i've got a php-script which is selecting 10 entrys from this database, according to the current pagenumber.
For example, if the current page is 2, the script should select every entry between id=20 and id=29.
Now, if i delete an entry, the id is lost. Therefore the script will only show 9 entrys when id28 has been deleted.
Is there a way to reassign the auto-increment values after e record has been deleted?
This is usually considered desirable: if entry number 28 is deleted, there will never again be an entry 28. If someone ever tries to refer to it, they're clearly trying to refer to the one that's been deleted, and you can report an error.
If you went back and reassigned 28 to some new entry, now you have no idea whether the person meant the old 28 or the new record.
Let's take a step back and revisit what you want to do. Your goal is not to show ten entries between 20 and 30. Your goal is to show ten entries that meet your criteria. For that, you can use the built-in LIMIT and OFFSET terms:
SELECT ...
FROM ...
WHERE ...
OFFSET 29
LIMIT 10
The OFFSET tells MySQL where to start counting and LIMIT tells it how many to count. MySQL will put together the whole result set, then give you 10 entries beginning at the 30th one. That's your fourth page of results. It does not remotely matter now what IDs they happen to have.
You should change the way you select entries for a page.
By using the LIMIT .. OFFSET clause, you will be able to select 10 entries, starting at Nth entry:
SELECT *
FROM table
ORDER BY id
LIMIT 10
OFFSET 19
LIMIT 10 means return only 10 rows
OFFSET 19 means return rows after 19th row
This way, it doesn't matter if some id has been removed and ids are not sequential.
Just change the OFFSET:
Page 1 => OFFSET 0
Page 2 => OFFSET 9
Page 3 => OFFSET 19
Page N => OFFSET (N-1)*10-1
Your question suggests a query like
SELECT columns FROM table WHERE id BETWEEN 20 AND 29;
or less elegant
SELECT columns FROM table WHERE id >= 20 AND id <= 29;
If so, I suggest you read up on the LIMIT clause and do somethong along the lines of
SELECT columns FROM table ORDER BY id LIMIT 20, 10;
You can but you shouldn't. If id=29 exists are you reset the auto-increment to 28, then there will be problems when auto-increment wants to use id=29 but the record already exists.
You'd be better off writing a query like so:
select * from table order by ID LIMIT n,10;
Where n is the page number*10
Reassign auto-increment values it's bad practice, because id, may used in relation with other tables.Use offset / limit construction, and forget about reassign auto-increment :)
As a direct answer to your question (auto_increment), you can change its value with the following query:
ALTER TABLE `your_table` AUTO_INCREMENT = 200
The next created item would have its next AI collumn value set to 200. This is useful in some cases, although I agree you would be better off using the LIMIT offsets.