sql-server - 创建有唯一索引但没有主键的表有什么影响?

标签 sql-server primary-key

制作一个简单的多对多交叉引用表的最佳方法是什么?该表只包含两列,而这两列本身就是其他表中的主键?

是否有人有具体证据支持或反对创建具有单个唯一索引但没有主键的表? (替代方案详述如下)。

换句话说:SQL Server 如何在内部唯一地标识 a) 具有主键的行和 b) 没有主键的行?

<小时/>

详细:

给定输入表:

CREATE TABLE Foo ( FooID bigint identity(1,1) not null primary key, other stuff... )
CREATE TABLE Bar ( BarID bigint identity(1,1) not null primary key, other stuff... )

三个基本选项是(在所有情况下都假设在 FooIDBarID 列上创建外键):

-- Option 1: Compound primary key
CREATE TABLE FooBarXRef ( 
    FooID bigint not null
  , BarID bigint not null
  , PRIMARY KEY ( FooID, BarID )
  , CONSTRAINT FK... etc
)

-- Option 2: Independent primary key + unique index
CREATE TABLE FooBarXRef ( 
    FooBarXRefID bigint identity(1,1) not null primary key
  , FooID bigint not null
  , BarID bigint not null
  , CONSTRAINT FK... etc
);
CREATE UNIQUE INDEX I_FooBarXRef_FooBar ON FooBarXRef ( FooID, BarID );

-- Option 3: Unique index, no explicit primary key:
CREATE TABLE FooBarXRef ( 
    FooID bigint not null
  , BarID bigint not null
  , CONSTRAINT FK... etc
);
CREATE UNIQUE INDEX I_FooBarXRef_FooBar ON FooBarXRef ( FooID, BarID );

外部参照表上有单独的标识 PK 是否多余?这可能会不必要地在数据库引擎上引入另一层约束检查?

另一方面,多列主键有问题吗?建议的解决方案是让外部参照表仅包含两个外键,并在这些列上定义唯一索引,但根本不定义主键...?

<小时/>

我怀疑这样做会导致 SQL Server 创建一个内部主键,以便唯一标识每一行,从而产生与显式定义主键相同的冗余约束 - 但我没有证据或文档支持这一点。 Other questions and answers建议默认情况下没有内部主键(即没有相当于 Oracle ROWID 的值);因为 %%physloc%% 是行当前存储位置的指示符,因此可能会发生更改。我的直觉是,引擎必须创建一些东西来唯一标识一行,以便实现游标、事务和并发。

最佳答案

主键的概念实际上与关系理论有关;通过跨多个表建立关系来维护引用完整性。默认情况下,SQL Server 引擎会在构建主键时创建唯一的聚集索引(假设此时不存在聚集索引)。

正是这个聚集索引在叶级别定义了唯一的行。对于具有非唯一聚集索引的表,SQL Server 会在键的末尾创建一个 4 字节的“唯一符”。

  • TestTable1 主键
  • TestTable2 主键和唯一非聚集
  • TestTable3 唯一集群
  • TestTable4 主聚集(与 Table1 和 Table3 相同,因为可以在非聚集索引上定义主键,所以我更喜欢它始终定义我想要的结构)。

TestTable2 是多余的,它创建一个唯一的聚集索引来存储其叶级别的所有记录。然后,它创建一个唯一的非聚集索引以再次强制唯一性。表上的任何更改都会影响集群,然后影响非集群。

TestTable1、TestTable3、TestTable4 在我的书中是平局,都创建了唯一的聚集索引结构。记录在页面上的存储方式没有物理差异。

但是对于 SQL Server 复制,所有复制的表都需要主键。如果您将来要使用复制,您可能需要确保所有唯一的聚集索引也是主键。

我似乎无法粘贴我的验证脚本,所以它们位于 hastebin 上。

http://hastebin.com/qucajimixi.vbs

关于sql-server - 创建有唯一索引但没有主键的表有什么影响?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21761994/

相关文章:

mysql - SQL 返回包含与主键相关的外键的表列表

sql-server - 为什么 Pivot 给出的错误为 'Incorrect syntax near ' 4721'

sql - SQL Server 中超过 VARCHAR(MAX) 值

sql - 多级父子关系

SQL 队列将在 2 周内获得工作负载 [SQL Server]

MySQL InnoDB : autoincrement non-primary key

sql-server - SQL Server Change Data Capture - 捕获进行更改的用户

java - 防止 hibernate 按列值重复行

sql - 更改主键

sql-server - 使用 CFINSERT 后获取主键 - ColdFusion