ALTER TABLE to add a composite primary key

377,512

Solution 1

ALTER TABLE provider ADD PRIMARY KEY(person,place,thing);

If a primary key already exists then you want to do this

ALTER TABLE provider DROP PRIMARY KEY, ADD PRIMARY KEY(person, place, thing);

Solution 2

You may simply want a UNIQUE CONSTRAINT. Especially if you already have a surrogate key. (example of an already existing surrogate key would be a single column that is an AUTO_INCREMENT )

Below is the sql code for a Unique Constraint

ALTER TABLE `MyDatabase`.`Provider`
    ADD CONSTRAINT CK_Per_Place_Thing_Unique UNIQUE (person,place,thing)
;

Solution 3

@Adrian Cornish's answer is correct. However, there is another caveat to dropping an existing primary key. If that primary key is being used as a foreign key by another table you will get an error when trying to drop it. In some versions of mysql the error message there was malformed (as of 5.5.17, this error message is still

alter table parent  drop column id;
ERROR 1025 (HY000): Error on rename of
'./test/#sql-a04_b' to './test/parent' (errno: 150).

If you want to drop a primary key that's being referenced by another table, you will have to drop the foreign key in that other table first. You can recreate that foreign key if you still want it after you recreate the primary key.

Also, when using composite keys, order is important. These

1) ALTER TABLE provider ADD PRIMARY KEY(person,place,thing);
and
2) ALTER TABLE provider ADD PRIMARY KEY(person,thing,place);

are not the the same thing. They both enforce uniqueness on that set of three fields, however from an indexing standpoint there is a difference. The fields are indexed from left to right. For example, consider the following queries:

A) SELECT person, place, thing FROM provider WHERE person = 'foo' AND thing = 'bar';
B) SELECT person, place, thing FROM provider WHERE person = 'foo' AND place = 'baz';
C) SELECT person, place, thing FROM provider WHERE person = 'foo' AND place = 'baz' AND thing = 'bar';
D) SELECT person, place, thing FROM provider WHERE place = 'baz' AND thing = 'bar';

B can use the primary key index in ALTER statement 1
A can use the primary key index in ALTER statement 2
C can use either index
D can't use either index

A uses the first two fields in index 2 as a partial index. A can't use index 1 because it doesn't know the intermediate place portion of the index. It might still be able to use a partial index on just person though.

D can't use either index because it doesn't know person.

See the mysql docs here for more information.

Solution 4

alter table table_name add primary key (col_name1, col_name2);

Solution 5

It`s definitely better to use COMPOSITE UNIQUE KEY, as @GranadaCoder offered, a little bit tricky example though:

ALTER IGNORE TABLE table_name ADD UNIQUES INDEX idx_name(some_id, another_id, one_more_id);

Share:
377,512

Related videos on Youtube

David542
Author by

David542

Updated on January 29, 2020

Comments

  • David542
    David542 over 4 years

    I have a table called provider. I have three columns called person, place, thing. There can be duplicate persons, duplicate places, and duplicate things, but there can never be a dupicate person-place-thing combination.

    How would I ALTER TABLE to add a composite primary key for this table in MySQL with the these three columns?

  • Adrian Cornish
    Adrian Cornish over 12 years
    @David542 No it doesn't - you can have only 1 primary key.
  • Marc B
    Marc B over 12 years
    @David: it's a single primary key composed of multiple fields, aka a composite key.
  • Adrian Cornish
    Adrian Cornish over 12 years
    @David542 Of course you can - this is a composite primary key consisting of 3 fields. The combination of the 3 fields must be unique.
  • plditallo
    plditallo over 10 years
    thanks for posting -- really got me out of battling with the ui
  • alwbtc
    alwbtc over 10 years
    one of the most precious answers in SO :)
  • kunigami
    kunigami over 9 years
    do you know if the second statement is atomic?
  • ZaneDarken
    ZaneDarken over 9 years
    Thank you, a constraint is what I wanted, I didn't know what to ask for in this initial post. Thanks for adding this to the thread.
  • granadaCoder
    granadaCoder over 9 years
    I typically use a surrogate key......then add a unique constraint. This way....if the "uniqueness" changes down the road, it is not much drama to tweak the constraint, vs messing with the primary-key. And if you have child tables that foreign-key references this table, you only have to FK the surrogate-key, not all 3 columns. –
  • Richie
    Richie almost 8 years
    @AdrianCornish Mysql Version is 5.6.28. The above statement is throwing an error: Incorrect table definition; there can be only one auto column and it must be defined as a key.
  • cs_alumnus
    cs_alumnus over 7 years
    @Richie if modifying an existing table, you may need to remove the auto increment property from the offending column, drop the existing primary key on that column, create a new primary key, then readd the auto increment and adjust the starting value as required. Sounds like a different question/configuration that needs more details to be answered.
  • oldboy
    oldboy almost 5 years
    beautiful. i wish i was better at MySQL
  • PAA
    PAA almost 5 years
    @All - Could you please share JPA equivalent for the same ?