我是SQL Server的新手,在学习聚集索引时感到困惑!
唯一键是聚集索引还是非聚集索引?唯一键仅在列中包括null的情况下持有唯一值,因此根据这个概念,唯一键应该是聚集索引,对吗?但是当我阅读MSDN的文章时感到困惑。
创建唯一约束时,默认会创建一个唯一的非聚集索引来强制执行唯一约束。如果表上不存在聚集索引,则可以指定唯一的聚集索引。
请帮助我更好地理解这个概念,谢谢。
我是SQL Server的新手,在学习聚集索引时感到困惑!
唯一键是聚集索引还是非聚集索引?唯一键仅在列中包括null的情况下持有唯一值,因此根据这个概念,唯一键应该是聚集索引,对吗?但是当我阅读MSDN的文章时感到困惑。
创建唯一约束时,默认会创建一个唯一的非聚集索引来强制执行唯一约束。如果表上不存在聚集索引,则可以指定唯一的聚集索引。
请帮助我更好地理解这个概念,谢谢。
在SQL Server索引中,有三种实现唯一性的方法。
无论它们是聚集索引还是非聚集索引,都与使用这些方法声明索引是否唯一无关。
这三种方法都可以创建聚集索引或非聚集索引。
默认情况下,如果您没有指定任何不同的选项(并且如果不存在冲突的聚集索引,则PK默认将被创建为 CLUSTERED
),则唯一约束和唯一索引将创建非聚集索引,但您可以为它们中的任何一个显式指定 CLUSTERED
/ NONCLUSTERED
。
示例语法如下:
CREATE TABLE T
(
X INT NOT NULL,
Y INT NOT NULL,
Z INT NOT NULL
);
ALTER TABLE T ADD PRIMARY KEY NONCLUSTERED(X);
--Unique constraint NONCLUSTERED would be the default anyway
ALTER TABLE T ADD UNIQUE NONCLUSTERED(Y);
CREATE UNIQUE CLUSTERED INDEX ix ON T(Z);
DROP TABLE T;
对于未指定为唯一的索引,SQL Server 将会默默地将它们变为唯一。对于聚集索引,这是通过在重复键后附加一个唯一标识符来完成的。对于非聚集索引,则会添加行标识符(逻辑或物理)到键中以保证唯一性。
唯一索引可以是聚集或非聚集的。 但如果您有可空列,则 NULL 值应该是唯一的(只有一个列为 null 的行)。 如果您想存储多个 NULL,可以使用过滤器“where columnName is not null”创建索引。
所有提供的答案都非常有帮助,但我想添加一些详细的答案,以便对其他人也有所帮助。
情况1:主键默认为聚集索引
在这种情况下,我们只创建主键,当我们检查表上创建的索引类型时,我们会注意到它自动创建了聚集索引。
USE TempDB
GO
-- Create table
CREATE TABLE TestTable
(ID INT NOT NULL PRIMARY KEY,
Col1 INT NOT NULL)
GO
-- Check Indexes
SELECT OBJECT_NAME(OBJECT_ID) TableObject,
[name] IndexName,
[Type_Desc] FROM sys.indexes
WHERE OBJECT_NAME(OBJECT_ID) = 'TestTable'
GO
-- Clean up
DROP TABLE TestTable
GO
情境二:将主键定义为非聚集索引
在这种情况下,我们将明确将主键定义为非聚集索引,并将其创建为非聚集索引。这证明了主键可以是非聚集索引。
USE TempDB
GO
-- Create table
CREATE TABLE TestTable
(ID INT NOT NULL PRIMARY KEY NONCLUSTERED,
Col1 INT NOT NULL)
GO
-- Check Indexes
SELECT OBJECT_NAME(OBJECT_ID) TableObject,
[name] IndexName,
[Type_Desc] FROM sys.indexes
WHERE OBJECT_NAME(OBJECT_ID) = 'TestTable'
GO
-- Clean up
DROP TABLE TestTable
GO
情境三: 当另一列被定义为聚集索引时,主键默认为非聚集索引
在这种情况下,我们将在另一列上创建聚集索引,SQL Server会自动创建一个作为非聚集索引的主键,因为已经在另一列上指定了聚集索引。
-- Case 3 Primary Key Defaults to Non-clustered Index
USE TempDB
GO
-- Create table
CREATE TABLE TestTable
(ID INT NOT NULL PRIMARY KEY,
Col1 INT NOT NULL UNIQUE CLUSTERED)
GO
-- Check Indexes
SELECT OBJECT_NAME(OBJECT_ID) TableObject,
[name] IndexName,
[Type_Desc] FROM sys.indexes
WHERE OBJECT_NAME(OBJECT_ID) = 'TestTable'
GO
-- Clean up
DROP TABLE TestTable
GO
情景4:主键默认为聚集索引,其他索引默认为非聚集索引
在这种情况下,我们将在两个表上创建两个索引,但不会指定列上的索引类型。当我们检查结果时,我们会注意到主键自动默认为聚集索引,而另一列作为非聚集索引。
-- Case 4 Primary Key and Defaults
USE TempDB
GO
-- Create table
CREATE TABLE TestTable
(ID INT NOT NULL PRIMARY KEY,
Col1 INT NOT NULL UNIQUE)
GO
-- Check Indexes
SELECT OBJECT_NAME(OBJECT_ID) TableObject,
[name] IndexName,
[Type_Desc] FROM sys.indexes
WHERE OBJECT_NAME(OBJECT_ID) = 'TestTable'
GO
-- Clean up
DROP TABLE TestTable
GO
参考:上述内容参考自该文章
以下是关于IT技术的翻译: