2

i have a problem case with auto_incrementing, this is my table i have first it was so smooth to incrementing id*

id*      name
1        name1
2        name2
3        name3
4        name4
5        name5
6        name6

but when I delete a record and insert a new record the id starts from 7.

id*      name
1        name1
2        name2
3        name3
5        name5
6        name6
7        name7

this is what i want to make:

id*      name
1        name1
2        name2
3        name3
4        name7
5        name5
6        name6

I would like a solution where every number is filled in, so if I delete a row the next autoinc number will be the number that I deleted not the next number higher.

Toby Allen
  • 10,997
  • 11
  • 73
  • 124
JON PANTAU
  • 395
  • 4
  • 14
  • 1
    No there is no way to easily reinit autoincrement items also it not so good idea, but there is some solution's present check here: http://stackoverflow.com/questions/740358/mysql-reorder-reset-auto-increment-primary-key – Armen Jan 02 '16 at 09:45
  • 3
    What you are trying to do is not really safe. Imagine you have another table with foreign key this 'id'. In case you delete a row and try to swift all other rows one up, the relation between the tables will break. – Stavros Jan 02 '16 at 09:46
  • Never mess with the aut-increment! – juergen d Jan 02 '16 at 09:48
  • I'd suggest thinking about why you think you want this, and maybe asking a question about that. – CollinD Jan 02 '16 at 09:48
  • What is your goal behind this?! – Yazid Erman Jan 02 '16 at 09:49
  • agree with @Stavros .It's not a good way to do so you can create one another column like duplicate_id and you can set the data like same you want but you always need to check the last biggest value and insert biggest+1 value.auto-increment cant give you as you want . – Alfiza malek Jan 02 '16 at 09:53
  • It is not recommended to mess with Auto Increment . Just imagine if you had to re order 1million of entries , what would be the performance of the program . I would agree with the approach of @CollinD . – Amar Shukla Jan 02 '16 at 10:01
  • 1
    Why do you want to do this? It is non standard and there is probably a differnt solution that would work better. Try to explain why you need to do this – Toby Allen Jan 02 '16 at 10:34

3 Answers3

6

First off, it's completely fine to have these gaps. There is no problem. It's just your OCD that forces you to think these numbers have to follow a pattern - they DON'T.

  • auto_increment is not a PHP feature, it's MySQL feature
  • auto_increment ensures every row gets a unique number. It doesn't deal with sequential numbers
  • auto_increment works safely in concurrent environment - that means there are a lot of users connecting to MySQL and doing stuff, and all of them have to be able to deal with the database and not get the same id for identifying a row. This is done through a rather complex process and this is one of the reasons why auto_increment yields gaps
  • auto_increment is used by InnoDB for physical organization of records on disk - it uses the feature of auto_increment and that one is producing a number that's larger than previous (that's what it does, larger than previous, not sequential). Using this, a b-tree is constructed and records are written in sequence on the hard drive. Tampering with auto_increment makes InnoDB rebalance the tree. It means it goes through records and recreates the index if you mess with it - that's something you don't want. Ever

When you think about it, what do you even get with sequential numbers? Nothing really, except your brain probably hurts less because there's some imaginary order.

For sequential numbers, use triggers to create them. auto_increment has one job and one job only - to produce unique numbers.

N.B.
  • 13,688
  • 3
  • 45
  • 55
1

If you're trying to get something that looks like a list, I suggest you leave the field "ID" as is and add another field to use for names sorted numerically.

Anyway, you can get the same result with just a query like this:

SELECT name, @Rk := @Rk+1 AS Rank
FROM mynamestable, (Select @Rk := 0) AS Rk 

Edit: This query will return all records in the field name from the table mynamestable and also a column (named Rank) that will be a numeric incremental (starting from 1) so the result will be something like:

name    Rank
Name1    1
Name2    2
Name3    3
genespos
  • 3,211
  • 6
  • 38
  • 70
  • Hi Can you explain in greater detail what this query is doing? – Toby Allen Jan 02 '16 at 10:36
  • @TobyAllen I added a little explain – genespos Jan 02 '16 at 10:57
  • How does this protect from generating the same number for a lot of concurrent requests? I see no constraints, you apparently assumed there's always going to be one person connected to MySQL doing work. This is a completely unsafe solution. – Mjh Jan 04 '16 at 09:18
  • @Mjh I pointed out that it's only a list. It returns only the current Ranking. This gives you the current ranking while preserving IDs. – genespos Jan 04 '16 at 09:27
  • So you agree it's not a real answer that will work safely in concurrent environment, right? – Mjh Jan 04 '16 at 09:33
  • @Mjh No! If Ryanto needs only a list and he doesn't need to update DB data I think it's a good and safe way – genespos Jan 04 '16 at 09:36
  • Ok, so what you are saying is that you didn't read the part where the OP mentions **delete** and you provided an answer that yields an enumerated list. How is that related to the question, which clearly states: **how to ensure no gaps in auto_increment numbers**? I'm not trying to belittle your contribution, but it's not answering the question. If the OP tried to use it, and if anyone tried to maintain the value of primary key using your query, it would be **unsafe**. I think that you can agree with me that your answer isn't the correct answer. – Mjh Jan 04 '16 at 10:19
-2

for it you can use trigger after delete. Update all ids (decrease 1) which greater than deleted id

CREATE TRIGGER update_ids AFTER DELETE ON test_table
FOR EACH ROW SET UPDATE test_table SET id = id - 1 WHERE id > OLD.id;

also you must reset auto_increment or write another trigger for insert, which update id to max(id)

Community
  • 1
  • 1
Ramin Darvishov
  • 1,043
  • 1
  • 15
  • 30
  • 1
    That's not what he is after and that would destroy any link between ids on different tables This is an awful idea even if it might solve the problem. – Toby Allen Jan 02 '16 at 10:35