更改表并将“标识”列作为主键有什么影响?

时间:2019-05-01 21:36:16

标签: sql sql-server primary-key

我正在解决由第三方建立的新数据库中的问题。

侧面注意:我刚刚加入了最初雇用第三方的公司。新的数据库不到两周,并且是在我上班的头几天启动的。

该数据库应该与旧数据库的架构匹配,但是不幸的是,第三方忘记了包含一些约束,触发器和索引。

两个数据库均为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而不是在新架构中复制主键?

编辑:我的计划基于回复中给出的建议

考虑到查询将需要执行的处理,我将在下班时间运行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
)

3 个答案:

答案 0 :(得分:0)

  1. 向表中添加CLUSTERED INDEX的开销很大。这将迫使页面重新排序,这意味着它将占用大量的IO,这取决于表可能需要一些时间。如果这样的话,很可能会锁定表一段时间。
  2. 是的,这是正确的语法,但是,我建议给您的Key命名。这会将语法更改为:

    ALTER TABLE [dbo].[SampleTable] ADD CONSTRAINT PK_SampleTable PRIMARY KEY CLUSTERED (ID ASC);

  3. 恐怕我们无法回答其他人的决定。

答案 1 :(得分:0)

不能保证SQL Server中的标识列是唯一的。正如documentation明确规定的那样:

  

列上的identity属性不能保证满足以下条件:

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

几乎总是将标识列声明为主键,但并非必须如此。

第二,如果确实将列设为主键,则通常将其聚集(除非已经存在另一个聚集索引)。如documentation中所述:

  

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

我猜想您希望将Identity列视为主键。您应该这样定义。您可以尝试将主键约束添加到现有表中(保持双手交叉,确保没有列重复)。

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

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

答案 2 :(得分:0)

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

为主键提供名称,而不是由系统生成匿名名称。

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