Why is the rejection of composite keys in favor of all tables using a single primary key named id? Cause generally all ORM follow this.
EDIT
You can use both. In some cases when making an association between an entity you can use both entity keys as a composite key.
As a rule of thumb I use generated ids for entities and composite keys for relationships.
I don't think there is a blanket statement that you should only ever use a single primary key named id.
Most people use a surrogate primary key as an auto generate int, because it isolates the primary key from ever needing to be changed, like if you make the PK the user name and they later changed their legal name. You would have to update the PK and all FK columns to reflect the new name. if you had used a surrogate primary key, you just update the user's name in one spot (because the tables join on the int not the name).
The size of a primary key is important because the PK is duplicated into every index you build on the table. If the PK is large (like a string) you have fewer keys per page in the index and the index will take more cache memory to store it. Ints are small.
Having a auto increment int PK lends itself to being a clustered index well, as rows are stored in this order and there is no need to go back and bump rows out of the way to insert a new row, you always add to the table's end.
I worked on an app with a 11 column primary key. It was always great fun retyping the list over and over and over every time I wanted to guarantee I was updating one row. It was a driver of bugs, MS-Access couldn't cope with more than 10 columns in a PK, etc.
Large composite keys are design smells that mean the table holds heterogenous entities or the designer wasn't really sure what it is that is unique about each entity. (Like assuming that hair color, eye color and body weight should be enough to unique identify an employee-- which isn't a good key because you'd need more and more and more columns to make it work and eventually that will include fields that are volatile and change a lot, like weight, or for some people hair color or lack there of.)
The only real limitation that I have run into using composite keys regards using an IN
expression with a subquery. This is a problem, because a subquery in an IN expression must return a single column (at least in T-SQL).
SELECT
emp.Name,
emp.UserDomain,
emp.UserID
FROM
employee emp
WHERE
???? IN (SELECT e.UserDomain, e.UserID FROM ... /* some complex
non-correlated subquery
or CTE */
)
There are always work-arounds, of course, but sometimes it could be an annoyance.
This is hardly a reason to avoid a composite key in places where it makes sense to use one.
Although I agree with most of the reasons given by other respondents, my primary reason for preferring a single-column integer key is that it makes writing a user interface much, much easier.
If you are using some kind of list control to represent your data (a list, list view, combo box, etc) you can uniquely relate each entry back to its database representation through a single integer value stored with the item. Most pre-written components already allow you to attach an integer to each item and for those that don't, it's very easy to extend the component to do so.
If you're passing data between a server application and a web page, it's much easier to store the single identifying value in the the id attribute of the widget that represents the data than to have to compose and parse multi-value ids.
Well, it's basically about keeping JOINs simple - which one is simpler to understand:
SELECT
p.ID, p.Name, p.City,
c.ID, c.Country, c.ISOCode
FROM
dbo.Parent p
INNER JOIN
dbo.Child c on c.ParentID = p.ID
or
SELECT
p.ID, p.Name, p.City,
c.ID, c.Country, c.ISOCode
FROM
dbo.Parent p
INNER JOIN
dbo.Child c ON c.ParentName = p.Name
AND c.ParentCity = p.City
AND c.ParentCountry = p.Country
If you have composite primary keys, anyone joining to your table from a child table must "drag along" all those columns, and all those columns are also going to be present in the child table and the JOIN statements are pretty messy. Much better to have a single (even surrogate) key for the JOIN!