Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Composite Primary Keys : Good or Bad?

Although one can use composite primary keys, for the case below, is it really a bad practice? The consensus on Stackoveflow seems to go both ways on this issue.

Why?


I want to store payments for the orders in a separate table. The reason is that, an order can have many items which are handled in a separate table in the form of many to many relationship. Now, if I don't use composite primary keys for my payment table, I'll lose my unique PaymentID:

[PaymentId] INT IDENTITY(1,1) NOT NULL PRIMARY KEY, [OrderId] INT NOT NULL PRIMARY KEY --Also a Foreign Key-- 

Now, if I just remove the Primary Key for the OrderId, I'll lose my one to one relationship here so Many OrderIds can be associated to many PaymentIds, and I don't want this.

This seems to be why other answers on SO have concluded (mostly) that the composite key is a bad idea. If it is bad, what's the best practice then?

like image 750
JAX Avatar asked Sep 27 '14 19:09

JAX


People also ask

When would you use a composite primary key?

A Composite Primary Key is created by combining two or more columns in a table that can be used to uniquely identify each row in the table when the columns are combined, but it does not guarantee uniqueness when taken individually, or it can also be understood as a primary key created by combining two or more ...

Are composite keys slower?

Having that composite primary key slows down SELECT s a tiny bit, though the effect is pretty much negligible and not worth worrying about. Having those columns indexed at all slows down your INSERT s, and you certainly are doing enough INSERT s to worry about it.


1 Answers

There is no conclusion that composite primary keys are bad.

The best practice is to have some column or columns that uniquely identify a row. But in some tables a single column is not enough by itself to uniquely identify a row.

SQL (and the relational model) allows a composite primary key. It is a good practice is some cases. Or, another way of looking at it is that it's not a bad practice in all cases.

Some people have the opinion that every table should have an integer column that automatically generates unique values, and that should serve as the primary key. Some people also claim that this primary key column should always be called id. But those are conventions, not necessarily best practices. Conventions have some benefit, because it simplifies certain decisions. But conventions are also restrictive.

You may have an order with multiple payments because some people purchase on layaway, or else they have multiple sources of payment (two credit cards, for instance), or two different people want to pay for a share of the order (I frequently go to a restaurant with a friend, and we each pay for our own meal, so the staff process half of the order on each of our credit cards).

I would design the system you describe as follows:

Products  : product_id (PK)  Orders    : order_id (PK)  LineItems : product_id is (FK) to Products             order_id is (FK) to Orders             (product_id, order_id) is (PK)  Payments  : order_id (FK)             payment_id - ordinal for each order_id             (order_id, payment_id) is (PK) 

This is also related to the concept of identifying relationship. If it's definitional that a payment exists only because an order exist, then make the order part of the primary key.

Note the LineItems table also lacks its own auto-increment, single-column primary key. A many-to-many table is a classic example of a good use of a composite primary key.

like image 156
Bill Karwin Avatar answered Sep 24 '22 12:09

Bill Karwin