views:

5851

answers:

14

Hi!

I'm currently designing a brand new database. In school, we always learned to put a primary key in each table.

I read a lot of articles/discussions/newsgroups posts saying that it's better to use unique constraint (aka unique index for some db) instead of PK.

What your point of view?

+22  A: 

Can you provide references to these articles?

I see no reason to change the tried and true methods. After all, Primary Keys are a fundamental design feature of relational databases.

Using UNIQUE to serve the same purpose sounds really hackish to me. What is their rationale?

Edit: My attention just got drawn back to this old answer. Perhaps the discussion that you read regarding PK vs. UNIQUE dealt with people making something a PK for the sole purpose of enforcing uniqueness on it. The answer to this is, If it IS a key, then make it key, otherwise make it UNIQUE.

chris
+7  A: 

It would be very rare denormalization that would make you want to have a table without a primary key. Primary keys have unique constraints automatically just by their nature as the PK.

A unique constraint would be used when you want to guarantee uniqueness in a column in ADDITION to the primary key.

The rule of always have a PK is a good one.

http://msdn.microsoft.com/en-us/library/ms191166.aspx

Scott Alan Miller
+3  A: 

Primary keys should be used in situations where you will be establishing relationships from this table to other tables that will reference this value. However, depending on the nature of the table and the data that you're thinking of applying the unique constraint to, you may be able to use that particular field as a natural primary key rather than having to establish a surrogate key. Of course, surrogate vs natural keys are a whole other discussion. :)

Unique keys can be used if there will be no relationship established between this table and other tables. For example, a table that contains a list of valid email addresses that will be compared against before inserting a new user record or some such. Or unique keys can be used when you have values in a table that has a primary key but must also be absolutely unique. For example, if you have a users table that has a user name. You wouldn't want to use the user name as the primary key, but it must also be unique in order for it to be used for log in purposes.

Noah Goodrich
With some DB, you can create a foreign key on a Unique Index's field(s)
vIceBerg
+1  A: 

the thing is that a primary key can be one or more columns which uniquely identify a single record of a table, where a Unique Constraint is just a constraint on a field which allows only a single instance of any given data element in a table.

PERSONALLY, I use either GUID or auto-incrementing BIGINTS (Identity Insert for SQL SERVER) for unique keys utilized for cross referencing amongst my tables. Then I'll use other data to allow the user to select specific records.

For example, I'll have a list of employees, and have a GUID attached to every record that I use behind the scenes, but when the user selects an employee, they're selecting them based off of the following fields: LastName + FirstName + EmployeeNumber.

My primary key in this scenario is LastName + FirstName + EmployeeNumber while unique key is the associated GUID.

Stephen Wrighton
That's how I do it as well: use 'private' id's (usually BIGINT) as primary keys. For normalization purposes I implement rules either in source or as triggers. I strongly believe that a database should capture all data, and manipulation of the data is done elsewhere.
slashmais
+4  A: 

A primary key is just a candidate key (unique constraint) singled out for special treatment (automatic creation of indexes, etc).

I expect that the folks who argue against them see no reason to treat one key differently than another. That's where I stand.

[Edit] Apparently I can't comment even on my own answer without 50 points.

@chris: I don't think there's any harm. "Primary Key" is really just syntactic sugar. I use them all the time, but I certainly don't think they're required. A unique key is required, yes, but not necessarily a Primary Key.

Dave
Thanks for the argument. But what's the harm? Is there justification for upsetting the paradigm?
chris
> automatic creation of indexes, etcNot all database automatically create an index for PKs. Oracle, for one, can just use an existing index.
A: 

If you plan on using LINQ-to-SQL, your tables will require Primary Keys if you plan on performing updates, and they will require a timestamp column if you plan on working in a disconnected environment (such as passing an object through a WCF service application).

If you like .NET, PK's and FK's are your friends.

Jarrett Meyer
+21  A: 

A Primary Key is really just a candidate key that does not allow for NULL. As such, in SQL terms - it's no different than any other unique key.

However, for our non-theoretical RDBMS's, you should have a Primary Key - I've never heard it argued otherwise. If that Primary Key is a surrogate key, then you should also have unique constraints on the natural key(s).

The important bit to walk away with is that you should have unique constraints on all the candidate (whether natural or surrogate) keys. You should then pick the one that is easiest to reference in a Foreign Key to be your Primary Key*.

You should also have a clustered index*. this could be your Primary Key, or a natural key - but it's not required to be either. You should pick your clustered index based on query usage of the table. When in doubt, the Primary Key is not a bad first choice.

  • Though it's technically only required to refer to a unique key in a foreign key relationship, it's accepted standard practice to greatly favor the primary key. In fact, I wouldn't be surprised if some RDBMS only allow primary key references.

  • Edit: It's been pointed out that Oracle's term of "clustered table" and "clustered index" are different than Sql Server. The equivalent of what I'm speaking of in Oracle-ese is an Index Ordered Table and it is recommended for OLTP tables - which, I think, would be the main focus of SO questions. I assume if you're responsible for a large OLAP data warehouse, you should already have your own opinions on database design and optimization.

Mark Brackett
Oracle wouldn't recommend a clustered index on every table.
Sorry - I'm a MSSQL guy, so I don't think in Oracle terms much. My understanding is that Oracle clustered tables and indexes have nothing do with SQL Server clustered indexes. The Oracle equivalent is an Index Ordered Table, which is recommended for at least OLTP tables.
Mark Brackett
+1  A: 

Unless the table is a temporary table to stage the data while you work on it, you always want to put a primary key on the table and here's why:

1 - a unique constraint can allow nulls but a primary key never allows nulls. If you run a query with a join on columns with null values you eliminate those rows from the resulting data set because null is not equal to null. This is how even big companies can make accounting errors and have to restate their profits. Their queries didn't show certain rows that should have been included in the total because there were null values in some of the columns of their unique index. Shoulda used a primary key.

2 - a unique index will automatically be placed on the primary key, so you don't have to create one.

3 - most database engines will automatically put a clustered index on the primary key, making queries faster because the rows are stored contiguously in the data blocks. (This can be altered to place the clustered index on a different index if that would speed up the queries.) If a table doesn't have a clustered index, the rows won't be stored contiguously in the data blocks, making the queries slower because the read/write head has to travel all over the disk to pick up the data.

4 - many front end development environments require a primary key in order to update the table or make deletions.

Chris OC
+2  A: 

We need to make a distinction here between logical constructs and physical constructs, and similarly between theory and practice.

To begin with: from a theoretical perspective, if you don't have a primary key, you don't have a table. It's just that simple. So, your question isn't whether your table should have a primary key (of course it should) but how you label it within your RDBMS.

At the physical level, most RDBMSs implement the Primary Key constraint as a Unique Index. If your chosen RDBMS is one of these, there's probably not much practical difference, between designating a column as a Primary Key and simply putting a unique constraint on the column. However: one of these options captures your intent, and the other doesn't. So, the decision is a no-brainer.

Furthermore, some RDBMSs make additional features available if Primary Keys are properly labelled, such as diagramming, and semi-automated foreign-key-constraint support.

Anyone who tells you to use Unique Constraints instead of Primary Keys as a general rule should provide a pretty damned good reason.

Michael Dorfman
A: 

posts saying that it's better to use unique constraint (aka unique index for some db) instead of PK

i guess that the only point here is the same old discussion "natural vs surrogate keys", because unique indexes and pk´s are the same thing.

translating:

posts saying that it's better to use natural key instead of surrogate key

DonOctavioDelFlores
+2  A: 

You should always have a primary key.

However I suspect your question is just worded bit misleading, and you actually mean to ask if the primary key should always be an automatically generated number (also known as surrogate key), or some unique field which is actual meaningful data (also known as natural key), like SSN for people, ISBN for books and so on.

This question is an age old religious war in the DB field.

My take is that natural keys are preferable if they indeed are unique and never change. However, you should be careful, even something seemingly stable like a persons SSN may change under certain circumstances.

JacquesB
agree, SSN for instance frequently changes as data entry errors are fixed andwhen people get a new one due to things like identity theft.
HLGEM
My question is not what you mean. It's really using a Primary Key versus a Unique Key Constraint.
vIceBerg
Okay. Then the answer is: You should always have a primary key. I think the people who adviced you otherwise have been confused, Note that a PK is also always a unique key-
JacquesB
A: 

I submit that you may need both. Primary keys by nature need to be unique and not nullable. They are often surrogate keys as integers create faster joins than character fileds and especially than multiple field character joins. However, as these are often autogenerated, they do not guarantee uniqueness of the data record excluding the id itself. If your table has a natural key that should be unique, you should have a unique index on it to prevent data entry of duplicates. This is a basic data integrity requirement.

Edited to add: It is also a real problem that real world data often does not have a natural key that truly guarantees uniqueness in a normalized table structure, especially if the database is people centered. Names, even name, address and phone number combined (think father and son in the same medical practice) are not necessarily unique.

HLGEM
A: 

I usually use both PK and UNIQUE KEY. Because even if you don't denote PK in your schema, one is always generated for you internally. It's true both for SQL Server 2005 and MySQL 5.

But I don't use the PK column in my SQLs. It is for management purposes like DELETEing some erroneous rows, finding out gaps between PK values if it's set to AUTO INCREMENT. And, it makes sense to have a PK as numbers, not a set of columns or char arrays.

yogman
upvoted to counter some random and senseless downvote
Steven A. Lowe
+1  A: 

I've written a lot on this subject: if you read anything of mine be clear that I was probably referring specifically to Jet a.k.a. MS Access.

In Jet, the tables are physically ordered on the PRIMARY KEY using a non-maintained clustered index (is clustered on compact). If the table has no PK but does have candidate keys defined using UNIQUE constraints on NOT NULL columns then the engine will pick one for the clustered index (if your table has no clustered index then it is called a heap, arguably not a table at all!) How does the engine pick a candidate key? Can it pick one which includes nullable columns? I really don't know. The point is that in Jet the only explicit way of specifying the clustered index to the engine is to use PRIMARY KEY. There are of course other uses for the PK in Jet e.g. it will be used as the key if one is omitted from a FOREIGN KEY declaration in SQL DDL but again why not be explicit.

The trouble with Jet is that most people who create tables are unaware of or unconcerned about clustered indexes. In fact, most users (I wager) put an autoincrement Autonumber column on every table and define the PRIMARY KEY solely on this column while failing to put any unique constraints on the natural key and candidate keys (whether an autoincrement column can actually be regarded as a key without exposing it to end users is another discussion in itself). I won't go into detail about clustered indexes here but suffice to say that IMO a sole autoincrement column is rarely to ideal choice.

Whatever you SQL engine, the choice of PRIMARY KEY is arbitrary and engine specific. Usually the engine will apply special meaning to the PK, therefore you should find out what it is and use it to your advantage. I encourage people to use NOT NULL UNIQUE constraints in the hope they will give greater consideration to all candidate keys, especially when they have chosen to use 'autonumber' columns which (should) have no meaning in the data model. But I'd rather folk choose one well considered key and used PRIMARY KEY rather than putting it on the autoincrement column out of habit.

Should all tables have a PK? I say yes because doing otherwise means at the very least you are missing out on a slight advantage the engine affords the PK and at worst you have no data integrity.

BTW Chris OC makes a good point here about temporal tables, which require sequenced primary keys (lowercase) which cannot be implemented via simple PRIMARY KEY constraints (SQL key words in uppercase).

onedaywhen