views:

135

answers:

4

I was always curious but can't find a concise answer. Any help?

+9  A: 

It cannot have more than one primary key. It can, however, have more than one column in the primary key. It can also have more than one unique index. Generally, the unique index is the primary key, but it is possible to have multiple unique indices on a single table. Off the top of my head I cannot think of an example, but when I do I will add it.

EDIT: Maybe this: In the US, the Department of Motor Vehicles might have a person table with 2 unique columns -- Social Security Number and Driver's License Number. Both should be unique.

MJB
It can also have more than one unique index.
Joe
Sorry, @Joe, I was editing when you commented.
MJB
But how would that work? What case would I need to have more than one column as a Primary Key? And if there are many columns as Primary Key, are they tupled?
Sergio Tapia
@Sergio To a bad example, a compound primary key might be name+surname.
ChrisW
@Sergio: You might want multiple columns in a primary key when you are dealing with a child table. For example, in an order entry system, OrderHeader might have a PK of OrderNum. OrderDetail might have a PK of OrderNum + LineNum. This is not real of course, but illustrative.
MJB
A many-to-many table is also a good example of a use for a compound primary key.
Bill Karwin
Another thing to consider: A primary key cannot have any NULL values, a unique index can have exactly 1
Scot Hauder
I'd suggest defining unique constraints instead of indexes, shows the intent better. And to be functionally equivilent to a primary key all columns in the unique constraint will need to be not nullable.
Shannon Severance
If you use surrogate primary keys (as opposed to natural), unique constraints (which are implemented in SQL Server via a unique index) are common. For example you might have a company table with an identity/sequence column as the PK, but still not want to allow duplicate company names.
Phil Sandler
Also, to clarify what Scot said, NULL is considered a unique value in SQL Server in a unique index/constraint. So for a composite index/constraint, you can only have one unique combination that includes NULL. I always thought this was counterintuitive, BTW.
Phil Sandler
@Phil Sandler - Not only is it counterintuitive, it is non-standard and specific to SQL Server within the Microsoft family of database products. I know that Access does not treat NULLs in unique constraints this way and I do not believe FoxPro does either. I've begged the MS people many times to provide an option to make unique constraints treat NULLs in a standard way (i.e. ignore them).
Thomas
@Shannon Severance: In SQL Server, a unique constraint and a unique index are the same thing. When implementing a unique constraint, it's created as being an index. And in SQL Server, you can't disable a unique constraint. For more info: http://msdn.microsoft.com/en-us/library/aa224827%28SQL.80%29.aspx
OMG Ponies
@OMG Ponies: An index is a physical construct. A constraint is a logical construct, which happens in SQL Server to be implemented with a unique index. When looking at someones design, a constraint communicates their intent, to me, of enforcing a rule. An developer created index might be there to enhance performance. Please declare constraints when the intent is to enforce rules. That being said, in 2008, a unique index with a where clause so it only indexes not null items is the only way I know to get an ANSI standard unique constraint.
Shannon Severance
@Shannon Severance: Believe me, I prefer the terminology "unique constraint" as opposed to index. I forgot to add that MySQL also doesn't have unique constraints, only unique indexes. But I also recall that the SQL Server syntax doesn't allow a single unique constraint on more than one column, have to use the unique index syntax...
OMG Ponies
@OMG Ponies: SQL Server has allowed multicolumned unique constraints since at least 2000. See _< table constraint >_ section of: http://msdn.microsoft.com/en-us/library/aa258255(v=SQL.80).aspx. It indicates repeating columns: ` (column [ ASC | DESC ] [ ,...n ] ) } ` (I may be misunderstanding what you are saying about SQL Server, and maybe you are talking about a different limitation.)
Shannon Severance
@Shannon Severance: I'm fuzzy on the details, I remember gbn listing differences a while back.
OMG Ponies
My very strong advice would be to avoid using unique constraints on nullable columns. Aside from the logical ambiguity of "unique" nulls, having a nullable column in a unique constraint at least suggests that some dependency on a candidate key is not being properly satisfied when it ought to be. Instead, create a new table with non-nullable columns and put the same unique constraint on that. That's what I would always do.
dportas
+4  A: 

As noted by MJB, a table can have at most one Primary Key, and should always have one (never zero). A table may, however, have multiple candidate keys - one of which is designated as the primary key. In normalization theory, the primary key is not critical; the candidate keys (the primary key is one of the candidate keys) are crucial in the theorems related to normalization.

An example of a table with three possible unique keys is, appropriately enough, the Table of Elements - where the Atomic Number, Symbol or Element Name could all be used as the primary key. Indeed, depending on whether you're doing chemistry or physics, the atomic number or symbol might be the most appropriate primary key, and the other would be an alternative key (and the element name would probably always be an alternative key rather than the primary key):

CREATE TABLE elements
(
    atomic_number   INTEGER NOT NULL UNIQUE CONSTRAINT c1_elements
                    CHECK (atomic_number > 0 AND atomic_number < 120),
    symbol          CHAR(3) NOT NULL UNIQUE CONSTRAINT c2_elements,
    name            CHAR(20) NOT NULL UNIQUE CONSTRAINT c3_elements,
    atomic_weight   DECIMAL(8,4) NOT NULL,
    stable          CHAR(1) DEFAULT 'Y' NOT NULL
                    CHECK (stable IN ('Y', 'N'))
);

(The notation is for Informix Dynamic Server; the differences between that and Microsoft SQL Server or any other SQL DBMS are pretty trivial. You can see that I've not designated any of the possible keys as 'the primary key'. If I did, I'd probably nominate Atomic_Number as the primary key.)


Thanks for the pointers, Thomas. I found this in the ISO/IEC 9075-2:2003 (SQL/Foundation):

§11.7 <unique constraint definition>

Function

Specify a uniqueness constraint for a table.

Format

<unique constraint definition> ::=
      <unique specification> <left paren> <unique column list> <right paren>
    | UNIQUE ( VALUE )
<unique specification> ::=
      UNIQUE
    | PRIMARY KEY
<unique column list> ::= <column name list>

Syntax Rules

  1. Each column identified by a <column name> in the <unique column list> is an operand of a grouping operation. The Syntax Rules of Subclause 9.10, “Grouping operations”, apply.
  2. Let T be the table identified by the containing <table definition> or <alter table statement>. Let TN be the <table name> of T.
  3. If <unique column list> UCL is specified, then

    a. Each <column name> in the <unique column list> shall identify a column of T, and the same column shall not be identified more than once.
    b. The set of columns in the <unique column list> shall be distinct from the unique columns of any other unique constraint descriptor that is included in the base table descriptor of T.
    c. Case:
    i. If the <unique specification> specifies PRIMARY KEY, then let SC be the <search condition>:

            UNIQUE ( SELECT UCL FROM TN )
            AND
            ( UCL ) IS NOT NULL
    

    ii. Otherwise, let SC be the <search condition>:

            UNIQUE ( SELECT UCL FROM TN )
    
  4. If UNIQUE (VALUE) is specified, then let SC be the <search condition>:

        UNIQUE ( SELECT TN.* FROM TN )
    
  5. If the <unique specification> specifies PRIMARY KEY, then for each <column name> in the explicit or implicit <unique column list> for which NOT NULL is not specified, NOT NULL is implicit in the <column definition>.

  6. A <table definition> shall specify at most one implicit or explicit <unique constraint definition> that specifies PRIMARY KEY.

  7. If a <unique constraint definition> that specifies PRIMARY KEY is contained in an <add table constraint definition>, then the table identified by the <table name> immediately contained in the containing <alter table statement> shall not have a unique constraint that was defined by a <unique constraint definition> that specified PRIMARY KEY.

Access Rules

None.

General Rules

  1. A <unique constraint definition> defines a unique constraint.
    NOTE 254 — Subclause 10.8, “<constraint name definition> and <constraint characteristics>”, specifies when a constraint is effectively checked.
  2. The unique constraint is not satisfied if and only if

      EXISTS ( SELECT * FROM TN WHERE NOT ( SC ) )
    

    is True.

Conformance Rules

  1. Without Feature S291, “Unique constraint on entire row”, conforming SQL language shall not contain UNIQUE(VALUE).
  2. Without Feature T591, “UNIQUE constraints of possibly null columns”, in conforming SQL language, if UNIQUE is specified, then the <column definition> for each column whose <column name> is contained in the <unique column list> shall contain NOT NULL.

NOTE 255 — The Conformance Rules of Subclause 9.10, “Grouping operations”, also apply.


Welcome to the wonderful world of the SQL standard! It seems that feature T591 allows for possibly null values in the columns of a UNIQUE constraint (but not in the columns of a PRIMARY KEY). The net result is that you have to understand how the following query works when there are NULLs in any of the columns in the UCL (unique column list):

      EXISTS ( SELECT * FROM TN WHERE NOT (
               UNIQUE ( SELECT UCL FROM TN ) ) )

And I know I am not sure how the UNIQUE operation works in those circumstances.


§8.10 <unique predicate>

Function

Specify a test for the absence of duplicate rows.

Format

<unique predicate> ::= UNIQUE <table subquery>

Syntax Rules

  1. Each column of user-defined type in the result of the <table subquery> shall have a comparison type.
  2. Each column of the <table subquery> is an operand of a grouping operation. The Syntax Rules of Subclause 9.10, “Grouping operations”, apply.

Access Rules

None.

General Rules

  1. Let T be the result of the .
  2. If there are no two rows in T such that the value of each column in one row is non-null and is not distinct from the value of the corresponding column in the other row, then the result of the <unique predicate> is True; otherwise, the result of the is False.

Conformance Rules

1) Without Feature F291, “UNIQUE predicate”, conforming SQL language shall not contain a <unique predicate>.

NOTE 193 — The Conformance Rules of Subclause 9.10, “Grouping operations”, also apply.

Jonathan Leffler
+1 This IMO, is by far the clearest explanation especially as it relates to relational theory and the proper vocabulary (e.g. candidate key). The only info I'd suggest to add is on SQL Server's non-standard handling of NULLs in unique constraints (i.e., they are treated as unique values so you can only have one).
Thomas
@Thomas: thanks. MS SQL Server may be non-standard, but it is far from being alone. The ISO SQL standard says nothing about indexes. I'm not sure what it says about nulls in unique constraints, but DB2 and Informix (following DB2, but since the mid-80s, long before IBM bought it) both allow only one NULL in a unique index (and enforce unique constraints via unique indexes). I believe it is Oracle that (non-standardly) allows for 'unique unless null' indexes.
Jonathan Leffler
@Jonathan Leffler - The ISO standard says nothing about indexes because indexes are implementation specific. However, it *does* say something about how unique constraints should be implemented and the standard states that they should ignore nulls.
Thomas
@Thomas: not doubting you - but can you quote the section of the standard where that is stated? SQL 1999 or SQL 2003 would be most convenient - I have those available to me. I am suspicious that it is implementation defined what happens, but open to persuasion otherwise by relevant quoting.
Jonathan Leffler
@Jonathan Leffler - Officially, the spec says: *The unique constraint is not satisfied if and only if EXISTS ( SELECT * FROM TN WHERE NOT ( SC ) )*. That will return false whenever the column in question is NULL which means that according to the spec, NULL should be excluded from evaluating uniqueness. Of course, the std also specifies that all columns in an unique constraint must be non-nullable. DB2 implements it this way. Oracle does not but does ignore nulls.
Thomas
@Jonathan Leffler - To answer your earlier question, here is a link to the SQL-92 spec: http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt. (Pulled that from Wikipedia). Look for `<unique constraint definition>`.
Thomas
@Jonathan Leffler - In researching on the net, I believe there is an option in the SQL:99 or SQL:2003 which provides for allowing nulls in unique constraint. I don't have access to the actual spec docs (although I'd like to) so I can't verify that part easily.
Thomas
@Jonathan Leffler - Presuming that the following test qualifies it would imply that NULL values should be ignored: Select Case When Exists( Select 1 From Table As T1 Where T1.PK <> T.PK And T1.Col = T.Col ) Then 'DUPLICATE' Else 'UNIQUE' End From Table As T. If you get `DUPLICATE` for any value, then the unique constraint should fail. The key is in the `SC` in the spec which is a search condition. Exists will return false when the result of the condition is UNKNOWN and thus, NULLS should be considered ignored in the uniqueness test.
Thomas
A: 

As far as I know, only one. However you can have more than one column (usually up to 8 or 20, depending on the RDBMS) combined with others as a composite key to uniquely identify the row. The lone primary key, single-column or composite, can also be used for joining to a foreign key in another table (one-to-many, many-to-one or many-to-many relationships).

Frank Computer
A: 

No, a table can't have more than one PK.

It can however have a composite key (one PK that contains more than one column in its definition). Also, you can have multiple unique constraints which also can span multiple columns.

Joe Philllips