ON [PRIMARY] 的意思是什么?

307
我正在创建一个SQL设置脚本,我正在使用别人的脚本作为示例。以下是脚本的示例:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[be_Categories](
    [CategoryID] [uniqueidentifier] ROWGUIDCOL  NOT NULL CONSTRAINT [DF_be_Categories_CategoryID]  DEFAULT (newid()),
    [CategoryName] [nvarchar](50) NULL,
    [Description] [nvarchar](200) NULL,
    [ParentID] [uniqueidentifier] NULL,
 CONSTRAINT [PK_be_Categories] PRIMARY KEY CLUSTERED 
(
    [CategoryID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

有人知道ON [PRIMARY]命令是什么吗?

4个回答

310

在创建Microsoft SQL服务器中的数据库时,您可以拥有多个文件组,存储可以创建在多个位置、目录或磁盘。每个文件组都可以命名。PRIMARY文件组是默认文件组,始终被创建,因此您提供的SQL会在PRIMARY文件组上创建表。

请参阅MSDN获取完整的语法。


195
这也意味着它通常是无用的,可以从脚本中安全地移除。 - MGOwen
是的,同样你可以省略变量初始化为0和false,因为这只是默认值,是吧? - Mark Sowul
14
除非您有使用它来优化性能的充分理由,否则可以省略它并让默认设置生效,这样做没有问题。(这就是MGOwen所说的“通常情况”所包含的内容。) 将变量初始化为0false是为了确保代码处于已知状态,这是逻辑和正确性方面的考虑,而不是优化方面的考虑。 - jpmc26
MSDN链接似乎会跳转到下载页面。 - RBT
4
我在脚本中看到了两次“ON PRIMARY”语法 - 一次用于表格,另一次用于表格约束。对于表格约束,它在存储方面表示什么意义?对我来说似乎不相关或冗余。从语法上讲,在表格级别只提及一次应该足够了,或者确实有可能将表格存储在PRIMARY文件组中,而表格约束数据存储在NON-PRIMARY文件组中吗? - RBT
2
以下是实际的 MSDN 链接。答案中的链接已经失效,我无法编辑该帖子! - shekhar

43

它指的是您要创建的对象所在的文件组。因此,您的主文件组可以位于服务器的 D:\ 驱动器上。然后,您可以创建另一个名为 Indexes 的文件组,该文件组可以位于服务器的 E:\ 驱动器上。


1
如果我将表存储在PRIMARY文件组上,而将表约束或索引数据结构存储在不同的文件组上,是否会对性能产生负面影响? - RBT
@RBT 这个问题有很多变量会影响到它,通常很多答案都会以“这取决于…”开头。请参考http://dba.stackexchange.com/questions/2626/when-should-nonclustered-indexes-be-stored-on-separate-filegroups以及相关问题。 - codingbadger

18

ON [PRIMARY]将在“Primary”文件组上创建结构。在这种情况下,主键索引和表将放置在数据库中的“Primary”文件组中。


12

请注意与文件组相关的一个重要行为。

使用OP的SQL脚本,您永远不能提到两个不同的文件组,即一个用于存储数据行,另一个用于索引数据结构。这是不允许的

原因是在此情况下创建的索引是基于表的主键的聚集索引。聚集索引的元数据表的数据行永远不能存储在两个不同的文件组中。

我的数据库有两个文件组:

  1. PRIMARY
  2. SECONDARY

现在,看一下下面的脚本,并通过SQL Server Management Studio(SSMS)执行它。接下来将会发生我们意料之外的事情。

即使我已经指定了一个不同的文件组([SECONDARY])来存储表的行数据,它仍将表的行数据以及与聚集索引相关的元数据存储在PRIMARY文件组上。我故意编写了这样的脚本来测试这种行为:

CREATE TABLE [dbo].[be_Categories](
    [CategoryID] [uniqueidentifier] ROWGUIDCOL  NOT NULL CONSTRAINT [DF_be_Categories_CategoryID]  DEFAULT (newid()),
    [CategoryName] [nvarchar](50) NULL,
    [Description] [nvarchar](200) NULL,
    [ParentID] [uniqueidentifier] NULL,
 CONSTRAINT [PK_be_Categories] PRIMARY KEY CLUSTERED 
(
    [CategoryID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [SECONDARY]
GO

有趣的是,上述脚本在没有任何错误的情况下运行结束。坦白地说,我原本期望出现运行时错误,因为我给出了两个不同的文件组。SQL Server在幕后默默地完成了这个技巧,而不会抛出任何错误。

注意:对于非聚集索引,索引可以存储在不同的文件组中。

下面显示的SQL脚本创建了一个非聚集索引。非聚集索引将在[SECONDARY]文件组上创建,而表的数据行将驻留在[PRIMARY]文件组中:

CREATE NONCLUSTERED INDEX [IX_Categories] ON [dbo].[be_Categories]
(
    [CategoryName] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [Secondary]
GO

您可以在这里了解更多信息,了解如何将非聚集索引存储在不同的文件组上,从而提高查询性能。


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