Sql 我有一个场景,在更改某些列后,我需要从同一个表插入到表中。问题是关键栏目

Sql 我有一个场景,在更改某些列后,我需要从同一个表插入到表中。问题是关键栏目,sql,sql-server,Sql,Sql Server,比方说 insert into A select * from A where col1 = "ABC" 导致一个错误,因为会有相同的主键列,我想从表的最大id自动递增 CREATE TABLE A( [WFID] [int] NOT NULL PRIMARY KEY, [EntityID1] [int] NOT NULL, [EntityID2] [int] NULL); INSERT INTO WFCustom SELECT * FROM WFCustom

比方说

insert into A  select * from A where col1 = "ABC"
导致一个错误,因为会有相同的主键列,我想从表的最大id自动递增

CREATE TABLE  A(
    [WFID] [int] NOT NULL PRIMARY KEY,
    [EntityID1] [int] NOT NULL,
    [EntityID2] [int] NULL);



INSERT INTO WFCustom
SELECT * FROM WFCustom
WHERE EntityID2 = 6008 , 
由于WFID是主键,因此获取错误:

违反主键约束“PK\u WF\u Custom”。无法在对象“dbo.WFCustom”中插入重复键。 声明已终止


您可以使用行号尝试以下查询

注:


正如@DanGuzman所建议的,当同一查询在读提交隔离级别下从多个会话运行时,插入可能会失败。因此,对于这种类型的场景,最好使用Identity列。

我的第一个建议是修复数据模型。这看起来像:

CREATE TABLE A (
    [WFID] int IDENTITY(1, 1) PRIMARY KEY,
    [EntityID1] [int] NOT NULL,
    [EntityID2] [int] NULL
);

INSERT INTO WFCustom (EntityID1, EntityID2)
    SELECT EntityID1, EntityID2
    FROM WFCustom
    WHERE EntityID2 = 6008; 
这是确保主键是唯一的最安全的方法,数据库会处理它

如果这不起作用,您可以指定一个新的。PSK提出的方法很好,尽管我将其写成:

INSERT INTO WFCustom (WFID, EntityID1, EntityID2)
    SELECT (COALESCE(MAX_WFID, 0) +
            ROW_NUMBER() OVER (ORDER BY WFID)
           ) as new_WFID,
           EntityID1, EntityID2
    FROM WFCustom CROSS JOIN
         (SELECT MAX(WFID) as MAX_WFID FROM WFCustom) m
    WHERE EntityID2 = 6008; 

在不带标识列的INSERT和SELECT上指定列列表。增量值将自动分配。我没有说identity column,我的意思是它应该有一个唯一的非空值,从select中删除名称将导致错误当您从INSERT columns列表中忽略identity columns时,identity columns将被分配一个唯一的非空值。试试看。@Dan不能将值NULL插入到“WFID”列、表“**.dbo.WFCustom”中;列不允许空值。插入失败。该语句已终止。您说您有一个标识列,但DDL显示您没有。如果此查询在读提交隔离级别中同时从两个会话运行,则可能会产生重复值。@DanGuzman,我已相应地更新了答案,感谢您指出。
INSERT INTO WFCustom (WFID, EntityID1, EntityID2)
    SELECT (COALESCE(MAX_WFID, 0) +
            ROW_NUMBER() OVER (ORDER BY WFID)
           ) as new_WFID,
           EntityID1, EntityID2
    FROM WFCustom CROSS JOIN
         (SELECT MAX(WFID) as MAX_WFID FROM WFCustom) m
    WHERE EntityID2 = 6008;