【问题标题】:Is it safe to add IDENTITY PK Column to existing SQL SERVER table?将 IDENTITY PK 列添加到现有 SQL SERVER 表是否安全?
【发布时间】:2021-12-10 07:31:40
【问题描述】:

在将我的一个 SQL SERVER 数据库中的所有表重建到一个新数据库后,我未能将许多表的“ID”列设置为 IDENTITY 和 PRIMARY KEY。他们中的大多数都有数据。

我发现了这个 T-SQL,并且已经成功地为几个表实现了它。新的/替换的 ID 列包含与前一列相同的值(仅仅是因为它们来自我导入的表中的自动递增列),并且我现有的存储过程仍然有效。

Alter Table ExistingTable
Add NewID Int Identity(1, 1)
Go

Alter Table ExistingTable Drop Column ID
Go

Exec sp_rename 'ExistingTable.NewID', 'ID', 'Column'

--Then open the table in Design View, and set the new/replaced column as the PRIMARY KEY
--I understand that I could set the PK when I create the new IDENTITY column

新的/替换的 ID 列现在是表中的最后一列,到目前为止,我还没有遇到调用存储过程的 ASP.Net/C# 数据访问对象的问题。

如前所述,这些表中的每一个都没有设置 PRIMARY KEY(也没有 FOREIGN KEY)。考虑到这一点,我是否应该采取任何其他步骤来确保数据库的完整性?

我遇到了this SO 帖子,它建议我应该运行“ALTER TABLE REBUILD”语句,但由于没有设置 PK,我真的需要这样做吗?

最终,我只是想确保我不会制造直到游戏后期才会出现的问题,并确保我正在实施的方法合理、合乎逻辑并确保数据完整性。

我想用正确的 PK/IDENTITY 列来 DROP/RECREATE 表可能是一个更好的选择,我可以编写一些 T-SQL 将现有数据转储到 TEMP 表中,然后删除/重新创建,然后重新- 使用 TEMP 表中的数据填充新表。我特别避免了这个选项,因为它看起来更具侵略性,而且我不完全理解它对依赖于这些表的存储过程/函数等意味着什么。

这是我执行过此操作的其中一张表的示例。可以看到NewID的值和原来的ID是一样的。enter image description here

【问题讨论】:

  • 你到底在问什么?您的标题询问如何将 IDENTITY 列添加到您的表中,但问题表明您已经知道如何做到这一点并且担心数据库的完整性。从技术上讲,您的数据库的完整性很少,因为没有主键 (PK),因此也没有外键 (FK)。但是,当您添加新的 IDENTITY 列时,分配的值将是任意的;它们与现有的非 PK "ID" 列没有任何关系。因此,如果您确实有任何“伪”关系,而不使用 FK,那么它现在不太可能匹配。
  • 对,所以您已经有一个包含可用主键值的列,并且可能其他表及其记录已经链接回它)即您有一个 ID 为 123 的地址记录和一个人员 ID 111,其 AddressId 为 123)。为什么不将此列设置为 PK,将其设置为标识并从已经存在的值的 max+1 开始呢?制作另一列将是一件令人头疼的事情,因为它会得到一堆不同的 auto inc 值,然后您需要使用旧引用将子记录连接起来并插入新引用......这一切听起来都很乏味!
  • 公平点。是的,我知道怎么做。问题是..我正在实施的方法是否足够合理以确保完整性?我知道它目前没有完整性;原来的表确实有 PK 的。我只是在导入这个新数据库时没有设置它们。一旦我设置了这些 PK,我以前这样做的方法是否值得确保这种完整性?此外,现有的非 PK、非 IDENTITY ID 是连续的,并且与我已经执行过的每个表完全匹配。我希望其他表的结果相同。但我明白你的意思。
  • 不太可能,@JeffKing,这些值将被完全任意分配。没有人保证,没有人,他们会是一样的。当您似乎没有 PK 并且可能没有聚集索引时尤其如此。
  • 这能回答你的问题吗? Adding an identity to an existing column 特别是这个答案stackoverflow.com/a/1730868/14868997

标签: sql-server primary-key alter-table


【解决方案1】:

试一试;它是从我们几年前在类似情况下使用的脚本中翻出来的,不记得它是针对哪个版本的 SQLS 使用的。如果它适用于您的场景,您可以将其调整到您的表中。。


SELECT MAX(Id)+1 FROM causeCodes -- run and use value below

CREATE TABLE [dbo].[CauseCodesW]( [ID] [int] NOT NULL IDENTITY(put_maxplusone_here,1), [Code] [varchar](50) NOT NULL, [Description] [varchar](500) NULL, [IsActive] [bit] NOT NULL )


ALTER TABLE CauseCodes SWITCH TO CauseCodesW;

DROP TABLE CauseCodes;

EXEC sp_rename 'CauseCodesW','CauseCodes';

ALTER TABLE CauseCodes ADD CONSTRAINT PK_CauseCodes_Id PRIMARY KEY CLUSTERED (Id);

SELECT * FROM CauseCodes;

您现在可以找到任何对该表具有 FK 的表并重新创建这些关系。

【讨论】:

  • 这太好了,谢谢!对于有很多行的表,我将使用这种方法,并回发它是如何进行的。
  • 不要忘记 SSMS 可以帮助您编写表格;右键单击“脚本为..创建..到新窗口”。通过拖放连接关系可以在数据库图表窗口中完成。
  • 我确实知道 CREATE TO 脚本。我不知道图表窗口和使用 GUI 来创建关系。我来自 MS Access 世界;这是否像 Access 中的功能,您可以在其中拖动列以创建关系?
  • 差不多; SSMS 似乎总是有点奇怪的功能组合,从来没有完全联系在一起。例如,如果您创建一个表列并刷新资源管理器树,智能仍然不知道它,您按 Ctrl Shift R;数据库图表是另一个奇怪的东西,就像它自己的断开连接的小世界,可能与其他表设计器不同步,但通常如果你只是使用它,并且在会话中单独使用它来进行设计更改,它会很好地工作。拖放带来一个窗口,您可以在其中确认关系,我认为您从父级拖动到子级
  • 表格视图也可用于重新设计列等,如果您将每个表格的视图从普通紧凑模式切换到标准..
猜你喜欢
  • 1970-01-01
  • 2015-08-03
  • 2022-10-05
  • 1970-01-01
  • 1970-01-01
  • 2015-01-09
  • 2018-07-13
  • 1970-01-01
  • 2010-09-10
相关资源
最近更新 更多