从另一个表中复制 IDENTITY 列并为丢失的记录生成新的 ID

Posted

技术标签:

【中文标题】从另一个表中复制 IDENTITY 列并为丢失的记录生成新的 ID【英文标题】:Copy IDENTITY column from another table and generate new IDs for missing records 【发布时间】:2021-11-14 20:46:28 【问题描述】:

我正在尝试将标识列从一个表复制到另一个表,但出现此错误:

无法更新身份列“ID”。

我尝试了以下代码:

ALTER TABLE [dbo].[TableA]
    ADD [ID] INT IDENTITY(20000,1), -- MAX(TableB.Id) < 20000

SET IDENTITY_INSERT TableA ON

UPDATE TableA 
SET TableA.[ID] = TableB.[ID]
FROM TableA 
INNER JOIN TableB ON TableB.ID = TableA.ID

SET IDENTITY_INSERT TableA OFF;

场景

我有两个 1:0-1 关系的表。

TableA: Code (PK)
A,
B,
C,
D

TableB: Id (PK), Code (Unique)
1, A
2, B
3, D

问题

如何

    创建新的标识列TableA.IdTableB.Id复制值 如果TableB.Id 中缺少TableA.Id,请确保它的新唯一值

【问题讨论】:

正如错误告诉你的那样,你不能 UPDATE IDENTITY 的值。您需要CREATE 一个新表,并将INSERT 数据放入启用IDENTITY_INSERT 的新表中。然后你可能想DROP你的旧表,并重命名你的新表。 dbfiddle.uk/… 外键约束有很多需要考虑的地方。见***.com/questions/1049210/…。另外,没有涉及的行数。在这些情况下,需要通过一个侧表,替换外键约束,删除旧表并将新表(sp_)重命名为旧表。恐怕这很乏味。 【参考方案1】:

=不是原始问题的真正答案,请参阅评论=

您不能更新本身就是您的加入条件的列。这是行不通的。

保持标识列完整的最安全方法是先从表 A 中的表 B 中删除行。 然后只需在 IDENTITY_INSERT ON 的情况下从表 B 插入表 A。 此外,这假设表 A 和表 B 共有的行之间存在 1:1 的关系。表 A 和表 B 之间的 1:0-1 关系意味着您需要从表 A 中的表 B 中捕获 ID 作为外键关系如果这会导致表 A 中的结果为 NULL,则改为单独列。

简而言之(伪代码),假设行之间的关系为 1:1:

DELETE FROM Table A WHERE Key EXISTS IN (SELECT Key FROM Table B)
;
SET IDENTITY_INSERT Table A ON
;
INSERT INTO Table A
(  id_column, [other_columns [, othercolumns] ] )
SELECT
  id_column, [other_columns [, othercolumns] ]
FROM Table B
;
SET IDENTITY_INSERT Table A OFF
;

【讨论】:

第一眼看起来不错,但 DELETE 不起作用,因为我有很多 FK 指向 TableA。

以上是关于从另一个表中复制 IDENTITY 列并为丢失的记录生成新的 ID的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 join codeigniter 从另一个表中获取值

PostgreSQL - 从连接表中选择聚合列并使用它来求和

如何使用第一个表中的逗号分隔值从另一个表中选择行? [复制]

从另一个查询调用时,返回 SETOF 记录会丢失记录类型

如何选择列并为不存在的列生成 Nan 值?

如何在数据表中动态创建列并为其赋值?