微软SQL表可以有多个主键吗?

3

我一直很好奇,但找不到简明的答案。有人能帮忙吗?

4个回答

9
它不能有多个主键,但可以在主键中有多个列。它也可以有多个唯一索引。通常,唯一索引是主键,但是在单个表上有多个唯一索引是可能的。我想不出一个例子,但是当我想到时我会添加它。
编辑:也许这样:在美国,车辆管理部门可能会有一个人员表格,其中有2个唯一列——社会安全号码和驾驶执照号码。两者都应该是唯一的。

2
另一个需要考虑的事情是:主键不能有任何NULL值,而唯一索引可以恰好有1个。 - Scot Hauder
2
我建议定义唯一约束而不是索引,这样更能表达意图。为了与主键在功能上等效,唯一约束中的所有列都需要是非空的。 - Shannon Severance
1
如果您使用代理主键(而不是自然主键),则唯一约束(在SQL Server中通过唯一索引实现)很常见。例如,您可能拥有一个公司表格,其中标识/序列列作为PK,但仍不希望允许重复的公司名称。 - Phil Sandler
1
@Phil Sandler - 这不仅违背直觉,而且是非标准和特定于Microsoft数据库产品家族中的SQL Server。我知道Access不会以这种方式处理唯一约束中的空值,我也不相信FoxPro会这样做。我已经多次恳求微软人提供选项,使唯一约束以标准方式处理空值(即忽略它们)。 - Thomas
@Shannon Severance:在SQL Server中,唯一约束和唯一索引是相同的东西。实现唯一约束时,它会被创建为一个索引。并且在SQL Server中,你无法禁用唯一约束。更多信息请参考:http://msdn.microsoft.com/en-us/library/aa224827(SQL.80).aspx - OMG Ponies
显示剩余10条评论

5
正如MJB所指出的,一个表最多只能有一个主键,并且应该始终有一个(不能为零)。然而,一个表可以有多个候选键,其中一个被指定为主键。在规范化理论中,主键并不是关键的;候选键(主键是候选键之一)在与规范化相关的定理中至关重要。
一个具有三个可能唯一键的表的例子是元素表 - 其中原子序数、符号或元素名称都可以用作主键。实际上,取决于你是做化学还是物理,原子序数或符号可能是最适合的主键,另一个将成为备用键(元素名称可能总是备用键而不是主键):
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'))
);

(该符号适用于Informix Dynamic Server;与Microsoft SQL Server或任何其他SQL DBMS之间的区别相当微小。您可以看到,我没有将任何可能的键指定为“主键”。如果我这样做,我可能会提名Atomic_Number作为the主键。)
感谢您的指导,Thomas。我在ISO/IEC 9075-2:2003(SQL/Foundation)中找到了这个:

§11.7 <unique constraint definition>

功能

为表指定唯一性约束。

格式

<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>

语法规则

  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.

访问规则

无。

常规规则

  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.

符合性规则

  1. 未启用功能S291“整个行上的唯一约束”的情况下,符合SQL语言不应包含UNIQUE(VALUE)。
  2. 未启用功能T591“可能为空列的唯一约束”的情况下,如果指定了UNIQUE,则在符合SQL语言中,每个列定义(<column definition>)都必须包含NOT NULL,其<column name>包含在<unique column list>中。

注255——子句9.10“分组操作”的符合性规则也适用。


欢迎来到SQL标准的奇妙世界!似乎功能T591允许在唯一约束的列中包含可能为空的值(但主键的列不能包含空值)。结果是,当UCL(唯一列列表)中的任何列中存在NULL时,您必须理解以下查询的工作原理:

      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>

功能

指定一个测试以确保没有重复的行。

格式

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

语法规则

  1. <表子查询>的结果中,每个用户定义类型的列都必须具有比较类型。
  2. <表子查询>中的每一列都是分组操作的操作数。适用于子句9.10“分组操作”的语法规则。

访问规则

无。

通用规则

  1. 令T为结果。
  2. 如果T中没有两行的每一列的值都非空且与另一行对应列的值不同,则<unique predicate>的结果为True;否则,结果为False。

一致性规则

1) 没有功能F291,“UNIQUE predicate”,符合SQL语言不得包含<unique predicate>

注193 - 子句9.10“分组操作”的一致性规则也适用。


+1 在我看来,这是目前为止最清晰的解释,特别是涉及关系理论和适当的术语(例如候选键)。我建议添加的唯一信息是关于SQL Server在唯一约束条件中对NULL的非标准处理(即将其视为唯一值,因此只能有一个)的信息。 - Thomas
@Jonathan Leffler - ISO标准对索引没有具体规定,因为索引是实现特定的。然而,它确实提到了唯一约束应该如何实现,并且标准规定它们应该忽略空值。 - Thomas
@Thomas:不是怀疑你——但你能引用标准中说明的那一部分吗?SQL 1999或SQL 2003最方便——我可以使用它们。我怀疑发生什么是实现定义的,但愿意通过相关引用来改变我的看法。 - Jonathan Leffler
@Jonathan Leffler - 回答你之前的问题,这里是 SQL-92 规范的链接:http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt(从维基百科中获取)。请搜索 "<unique constraint definition>"。 - Thomas
@Jonathan Leffler - 在网上查找资料时,我相信SQL:99或SQL:2003中有一种选项,可以允许在唯一约束条件下使用空值。虽然我很想查看实际的规范文档,但我没有权限验证该部分。 - Thomas
显示剩余3条评论

0
据我所知,只有一个。但是您可以将多个列(通常最多8或20个,具体取决于RDBMS)与其他列组合成复合键,以唯一标识行。孤立的主键,单列或复合键,也可用于与另一张表中的外键连接(一对多、多对一或多对多关系)。

0

不可以,一张表不能有多个主键。

但是,它可以有一个复合主键(一个包含多个列定义的主键)。此外,您可以拥有多个唯一约束,这些约束也可以跨越多个列。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接