更改表并将Identity列作为主键有什么影响?

问题描述 投票:1回答:3

我正在修复由第三方设置的新数据库的问题。

侧面说明:我刚刚加入了最初聘请第三方的公司。新数据库不到两周,并在我工作的头几天推出。

该数据库应该与旧数据库的模式匹配,遗憾的是第三方忘记了包含一些约束,触发器和索引。

这两个数据库都是SQL Server 2012

我希望改变一个当前没有旧模式中的主键的表。以下是简化的创建表语句

目前的生产

CREATE TABLE [dbo].[Table](
    [field] [varchar](255) NULL,
    [data] [varchar](255) NULL,
    [id] [int] IDENTITY(1,1) NOT NULL
) ON [PRIMARY]
GO

来自旧数据库的表

CREATE TABLE [dbo].[Table](
    [id] [int] NOT NULL,
    [field] [varchar](255) NULL,
    [data] [varchar](255) NULL,
PRIMARY KEY CLUSTERED 
(
    [id] 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
  1. 它会对ALTER生成表产生重大影响,并在主键中添加回原始数据库中存在的索引吗?有最佳实践指南吗?
  2. 这是用于更改生产表的适当的sql
ALTER TABLE [dbo].[Table] ADD PRIMARY KEY CLUSTERED 
(
    [id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
  1. 是否存在编程原因,为什么第三方开发人员可能决定使用IDENTITY而不是在新架构中复制主键?

EDIT: My plan based off the advice given in the responses

考虑到查询需要执行的处理,我将在非工作时间运行Alters。我决定使用ALTER而不是清空表,并根据我的环境的业务需求重新填充它。

我已使用此查询确认IDENTITY列目前是唯一的

SELECT DISTINCT(id), COUNT(id)
FROM Table
GROUP BY id
HAVING Count(id) > 1

如果以上情况仍然存在,那么我将在非高峰时段运行以下内容:

ALTER TABLE [dbo].[Table] ADD CONSTRAINT PK_Table PRIMARY KEY CLUSTERED
(
    [id] ASC
)
sql sql-server primary-key
3个回答
0
投票
  1. CLUSTERED INDEX添加到表中是很昂贵的。它会强制重新排序页面,这意味着它将是IO密集型的,这取决于表格可能需要一些时间。如果是这样的话,它可能会暂时锁定表格。
  2. 是的,这是正确的语法,但是,我建议给你的密钥一个名字。这会将语法更改为: ALTER TABLE [dbo].[SampleTable] ADD CONSTRAINT PK_SampleTable PRIMARY KEY CLUSTERED (ID ASC);
  3. 我担心,我们无法回答其他人的决定。

0
投票

SQL Server中的标识列不保证是唯一的。正如documentation明确指出:

列上的标识属性不保证以下内容:

  • 值的唯一性 - 必须使用PRIMARY KEY或UNIQUE约束或UNIQUE索引强制实现唯一性。

标识列几乎总是被声明为主键,但它们不是必需的。

其次,如果您确实将列作为主键,那么它通常将被聚类(除非已存在另一个聚簇索引)。如documentation所述:

创建主键会自动创建相应的唯一聚簇索引,如果指定,则创建非聚簇索引。

我猜你想要将标识列视为主键。你应该这样定义它。您可以尝试将主键约束添加到现有表中(保持手指交叉,没有列具有重复项)。

您可能会发现清空表,添加正确的约束以及重新加载数据的性能更高。

如果您确实有主键,则有充分的理由将其作为标识列 - 这有助于避免页面碎片。新值永远不会小于现有值,因此新行将出现在“最后”数据页面上。


0
投票

这将是昂贵的操作,但它取决于表中的数据量和执行时间。

将名称指定给主键而不是系统生成的匿名名称。

想想表和数据的目的是什么?在哪里使用?

© www.soinside.com 2019 - 2024. All rights reserved.