39

Is it possible to auto-increment a non-primary key?

Table "book_comments"

book_id     medium_int
timestamp   medium_int
user_id     medium_int
vote_up     small_int
vote_down   small_int
comment     text
comment_id  medium_int

Primary key -> (book_id, timestamp, user_id)

There will be no other indexes on this table. However, I would like to make the comment_id column autoincrement so that I can easily create another table:

Table "book_comments_votes"

comment_id  (medium_int)
user_id     (medium_int)

Primary key -> (comment_id, user_id)

Users would be able to vote only once per book comment. This table enforces this rule by the primary key.

Question:

Is it possible to auto-increment a non-primary key - as in, auto-increment the comment_id column in table "book_comments"?


Alternatives, Discussion.

I would like to do this for simplicity as explained above. The alternatives are not promising.

  • Make the commnet_id PK and enforce integrity through a unique index on book_id, timestamp, user_id. In this case, I would create an additional index.
  • Keep the PK and replace the comment_id in the book_comments_votes with the entire PK. This would more than triple the size of the table.

Suggestions? Thoughts?

informatik01
  • 16,038
  • 10
  • 74
  • 104
ProfileTwist
  • 1,524
  • 1
  • 13
  • 18
  • Why can't you simply make `comment_id` the primary key? I don't understand why you would need the extra unique index. I'm probably just not fully understanding your problem. – Michael Mior Dec 29 '12 at 22:14
  • `comment_id` as the PK would not be enough to enforce data integrity - specifically that there are no other duplicates user votes for a specific book. That's why a unique index is needed with a composite key. – ProfileTwist Dec 30 '12 at 21:32
  • So users can only vote once per book, not once per book comment as you stated in your question? – Michael Mior Dec 30 '12 at 22:21

3 Answers3

52

Yes you can. You just need to make that column be an index.

CREATE TABLE `test` (
  `testID` int(11) NOT NULL,
  `string` varchar(45) DEFAULT NULL,
  `testInc` int(11) NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`testID`),
  KEY `testInc` (`testInc`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;


insert into test(
  testID,
 string
)
values (
1,
    'Hello'
);


insert into test( 
testID,
 string
)
values (
2,
    'world'
);

Will insert rows with auto-incrementing values for 'testInc'. However this is a really dumb thing to do.

You already said the right way to do it:

"Make the comment_id PK and enforce integrity through a unique index on book_id, timestamp, user_id."

That's exactly the way that you should be doing it. Not only does it provide you with a proper primary key key for the table which you will need for future queries, it also satisfies the principle of least astonishment.

Danack
  • 24,939
  • 16
  • 90
  • 122
  • 6
    "this is a really dumb thing to do". That's strong. Every quirk has its use case. I have large text-based keys which I'd rather not propagate throughout my design. A surrogate key fits the bill. – Robert May 04 '17 at 21:29
  • A surrogate key is what I suggested they use, instead of their original silly idea. – Danack May 04 '17 at 23:27
  • Thank you so much you are a big help :)) – Bynd Sep 20 '18 at 01:30
  • It's not just strong, it's a wrong comment. While he's right that having a proper key is a good thing. It doesn't mean that a complex key made of various columns is the best solution at all. a primary integer id is very portable, a complex key not necessarily. – John Nov 22 '18 at 00:06
  • even if it does allow auto_increment on any index, I'd at the very least make it a unique index. a non-unique index that auto increments seems like a recipe for disaster – ysth Jul 31 '20 at 05:29
2

You've existing table. If you already gave a primary key to comment_id and the only purpose is to set auto_increment. You can drop the primary key to that column. MySQL allows a column with any key property can access auto_increment. So better try an index or unique key to comment_id like below.

1.Remove Primary Key

ALTER TABLE `book_comments` MODIFY `comment_id` INT(5) NOT NULL;

ALTER TABLE `book_comments` DROP PRIMARY KEY ;
  1. Add AUTO_INCREMENT with UNIQUE_KEY property.

ALTER TABLE 'brand_keywords' CHANGE COLUMN 'comment_id' 'comment_id' INT(5) NOT NULL AUTO_INCREMENT UNIQUE;

Community
  • 1
  • 1
Gowtham Vakani
  • 358
  • 3
  • 10
0

As of MySQL 5.5, it seems to be possible without an index or primary key an INT field to be provided with autoincrement.

loebe
  • 17
  • 3
  • 1
    Can you ? Post your code please. I tried in 5.5.23 and 5.6.12: > create table test ( user varchar(20) not null, id int auto_increment, primary key(user)); ERROR 1075 (42000): Incorrect table definition; there can be only one auto column and it must be defined as a key – phil_w Nov 04 '14 at 19:06
  • 1
    Sorry u have to add an Index, my fault. create table test ( user varchar(20) not null, id int auto_increment, index (id), primary key (user)) – loebe Feb 02 '15 at 09:59
  • Can you mention the reference? – Sajjad Jan 24 '22 at 09:32