【问题标题】:Non nullable column with clustered unique index. Why need Primary Key?具有聚集唯一索引的不可为空的列。为什么需要主键?
【发布时间】:2013-03-21 19:25:15
【问题描述】:

在 SQL Server 中,我有一个 不可为空的列,上面有一个唯一聚集索引。 如果我将此列设为主键,则会自动创建完全相同的索引加上 该列被识别为主键。

我理解抽象/语义的区别。

(主键标识实体,而具有此索引的任何其他列可能不会。
例如,Person 可以具有唯一的、不可为空的电子邮件字段...但可以更改)

但困扰我的是数据库引擎本身的实际差异

如果我只创建一个 Id 列,使其不可为空,为它创建一个唯一的聚集索引,使其标识增量,但没有主键约束,会发生什么?

主键约束在什么情况下发挥作用?

(在提出这个问题之前,我已经查看了许多相关问题,但我看到的所有答案都以抽象/理论解释结束)。

【问题讨论】:

    标签: sql-server sql-server-2008 indexing unique-constraint clustered-index


    【解决方案1】:

    真的没有什么不同。您指定PRIMARY KEY 来传达您的意图,而不是让引擎做任何不同的事情。在构建查询计划时,优化器仍将对其所有属性使用唯一性,并且仍将对其所有属性使用聚集索引,无论您是否在技术上将其创建为PRIMARY KEY。创建FOREIGN KEY 时,您仍然可以引用指定为唯一的列(集群或非集群)。区别仅在于元数据 (sys.indexes.is_primary_key) 和 SSMS 对您的表示(哦,事实上您可以在 NULLable 列上创建唯一聚集索引,但不能在该列上创建 PRIMARY KEY )。

    事实上,在很多情况下,您都希望将聚集索引与PRIMARY KEY 完全分开。例如,如果您有一个 PK 是 GUID 的表,并且您通常针对该表运行日期范围查询,那么您最好让 PK 是非聚集的并且在自然增加的列上具有聚集索引( datetime 列) - 既可以最大程度地减少大量插入活动的页面拆分,也可以最好地协助日期范围查询。非聚集索引非常适合查找单个 GUID。 (我想提一下,因为很多人认为主键必须是集群的。不是真的。)

    另外值得注意的是,如果您创建 PRIMARY KEY 约束,然后使用 DROP_EXISTING 创建具有相同名称的唯一聚集索引,is_primary_key 列仍将是 1,并且对象资源管理器仍将显示Keys 下的索引名称。

    【讨论】:

    • 谢谢! GUID 的一个很好的例子。不明白为什么这被否决了。
    【解决方案2】:

    这是一种情况 - 数据映射框架的大量代码查看数据库元数据(什么是主键、外键等)以确定代码的执行方式。例如Hibernate requires a primary key

    一个典型的场景可能是为更新生成一个where 子句。

    【讨论】:

    • 如果它是表上唯一的唯一索引,那么 Hibernate 甚至不能选择唯一索引?如果有多个,我可以理解它会感到困惑,但要求显式主键似乎是暂时的疏忽。你知道这是一个永久性的限制,还是他们最终会解决的这些愚蠢的事情中的另一个?
    • @AaronBertrand - 通常框架的方法是查找主键,因为这是创建表时的正常情况。一些框架确实会查看唯一索引。但是,我不能代表那个特定的项目(Hibernate)来说明他们正在计划什么。你说的当然是可以做到的。这只是它在优先级列表中的位置的问题。
    猜你喜欢
    • 2012-12-21
    • 2014-07-30
    • 1970-01-01
    • 1970-01-01
    • 2011-05-15
    • 2017-02-28
    • 2012-12-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多