62

I acquired a database from another developer. He didn't use auto_incrementers on any tables. They all have primary key ID's, but he did all the incrementing manually, in code.

Can I turn those into Auto_incrementers now?


Wow, very nice, thanks a ton. It worked without a hitch on one of my tables. But a second table, i'm getting this error...Error on rename of '.\DBNAME#sql-6c8_62259c' to '.\DBNAME\dealer_master_events'

casperOne
  • 73,706
  • 19
  • 184
  • 253
Gene R
  • 1,555
  • 5
  • 19
  • 32

7 Answers7

113

For example, here's a table that has a primary key but is not AUTO_INCREMENT:

mysql> CREATE TABLE foo (
  id INT NOT NULL,
  PRIMARY KEY (id)
);
mysql> INSERT INTO foo VALUES (1), (2), (5);

You can MODIFY the column to redefine it with the AUTO_INCREMENT option:

mysql> ALTER TABLE foo MODIFY COLUMN id INT NOT NULL AUTO_INCREMENT;

Verify this has taken effect:

mysql> SHOW CREATE TABLE foo;

Outputs:

CREATE TABLE foo (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=latin1

Note that you have modified the column definition in place, without requiring creating a second column and dropping the original column. The PRIMARY KEY constraint is unaffected, and you don't need to mention in in the ALTER TABLE statement.

Next you can test that an insert generates a new value:

mysql> INSERT INTO foo () VALUES (); -- yes this is legal syntax
mysql> SELECT * FROM foo;

Outputs:

+----+
| id |
+----+
|  1 | 
|  2 | 
|  5 | 
|  6 | 
+----+
4 rows in set (0.00 sec)

I tested this on MySQL 5.0.51 on Mac OS X.

I also tested with ENGINE=InnoDB and a dependent table. Modifying the id column definition does not interrupt referential integrity.


To respond to the error 150 you mentioned in your comment, it's probably a conflict with the foreign key constraints. My apologies, after I tested it I thought it would work. Here are a couple of links that may help to diagnose the problem:

Community
  • 1
  • 1
Bill Karwin
  • 538,548
  • 86
  • 673
  • 828
  • Wow, very nice, thanks a ton. It worked without a hitch on one of my tables. But a second table, i'm getting this error...Error on rename of '.\DBNAME\#sql-6c8_62259c' to '.\DBNAME\dealer_master_events' (errno: 150) – Gene R Oct 31 '08 at 19:04
  • 2
    if the primary key is already acting as a foreign key somewhere else, you will need to disable foreign-key checks before you run the alter table query. `set foreign_key_checks = 0; ALTER TABLE buyer MODIFY COLUMN _id INT NOT NULL AUTO_INCREMENT; set foreign_key_checks = 1;` – mugume david Jul 16 '15 at 06:54
  • @mugumedavid, that's not correct. I just tried it. You can change the parent table and make its primary key auto_increment even if there are dependent tables referencing it. Likewise in the other direction, if you want to add auto_increment to a PK that is also an FK (not sure why you'd do that). – Bill Karwin Jul 16 '15 at 19:15
  • 1
    @billkarwin i honestly failed to in my case, which led me to this page and http://dba.stackexchange.com/questions/90162/adding-autoincrement-to-id-already-part-of-foreign-key It could be my db version or myIsam vs Innodb – mugume david Jul 17 '15 at 13:13
6

None of the above worked for my table. I have a table with an unsigned integer as the primary key with values ranging from 0 to 31543. Currently there are over 19 thousand records. I had to modify the column to AUTO_INCREMENT (MODIFY COLUMN'id'INTEGER UNSIGNED NOT NULL AUTO_INCREMENT) and set the seed(AUTO_INCREMENT = 31544) in the same statement.

ALTER TABLE `'TableName'` MODIFY COLUMN `'id'` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT = 31544;
GDP
  • 8,109
  • 6
  • 45
  • 82
  • This is crucial, and was the only thing that worked for me (MySQL 5.6/OSX). If you already have a primary key that is *not* autoincrement and you alter it to be autoincrement, you must (at least in my configuration, which is 100% defaults) do them in the same statement, otherwise INSERTs that do not supply the ID will fail with e.g. `ERROR 1364 (HY000): Field 'id' doesn't have a default value`. – Zac B Oct 10 '18 at 21:48
5

I'm guessing that you don't need to re-increment the existing data so, why can't you just run a simple ALTER TABLE command to change the PK's attributes?

Something like:

ALTER TABLE `content` CHANGE `id` `id` SMALLINT( 5 ) UNSIGNED NOT NULL AUTO_INCREMENT 

I've tested this code on my own MySQL database and it works but I have not tried it with any meaningful number of records. Once you've altered the row then you need to reset the increment to a number guaranteed not to interfere with any other records.

ALTER TABLE `content` auto_increment = MAX(`id`) + 1

Again, untested but I believe it will work.

Stephen Walcher
  • 2,565
  • 1
  • 21
  • 22
  • I don't think the second `ALTER` is needed. And I think that it will fail, since the syntax calls for a "value", not an "expression". – Rick James May 01 '19 at 18:18
2

This worked for me (i wanted to make id primary and set auto increment)

ALTER TABLE table_name CHANGE id id INT PRIMARY KEY AUTO_INCREMENT;

2
ALTER TABLE `foo` MODIFY COLUMN `bar_id` INT NOT NULL AUTO_INCREMENT;

or

ALTER TABLE `foo` CHANGE `bar_id` `bar_id` INT UNSIGNED NOT NULL AUTO_INCREMENT;

But none of these will work if your bar_id is a foreign key in another table: you'll be getting

an error 1068: Multiple primary key defined

To solve this, temporary disable foreign key constraint checks by

set foreign_key_checks = 0;

and after running the statements above, enable them back again.

set foreign_key_checks = 1;
Dima Dz
  • 512
  • 1
  • 5
  • 17
0

Yes, easy. Just run a data-definition query to update the tables, adding an AUTO_INCREMENT column.

If you have an existing database, be careful to preserve any foreign-key relationships that might already be there on the "artificially created" primary keys.

Alex Weinstein
  • 9,823
  • 9
  • 42
  • 59
-2

As long as you have unique integers (or some unique value) in the current PK, you could create a new table, and insert into it with IDENTITY INSERT ON. Then drop the old table, and rename the new table.

Don't forget to recreate any indexes.

Adam
  • 7,800
  • 2
  • 25
  • 24