【问题标题】:Duplicate SQL records to the same table with manually auto increment id使用手动自动递增 id 将 SQL 记录复制到同一张表中
【发布时间】:2017-05-23 20:48:51
【问题描述】:

我正在尝试编写一个返回这些记录的查询:

select * 
from [CloneConfiguration] 
where InstrumentId = 2

并通过更改以下列将它们插入到同一个表中:

  1. Id - 新记录需要一个唯一的 id 编号(因为它是主键,没有它定义为自动递增)

  2. Instrument id - 将仪器 ID 更改为另一个数字(例如 3)

我尝试了以下不起作用的查询。

INSERT INTO [CloneConfiguration] 
   SELECT 
       MAX(Id) + 1, 3,
       [SourceCCy1Id], [SourceCCy2Id], [SourceProviderId], 
       [TargetCCy1Id], [TargetCCy2Id], [TargetProviderId], [Remark]
   FROM 
       [CloneConfiguration] 
   WHERE 
       InstrumentId =2 

错误:

选择列表中的“CloneConfiguration.SourceCCy1Id”列无效,因为它既不包含在聚合函数中,也不包含在 GROUP BY 子句中。

【问题讨论】:

  • 如果你使用max函数,你需要一个group by子句
  • 请为您的 dbms 添加标签
  • 根据使用的非标准方括号添加了sql-servertsql 标签

标签: sql sql-server tsql


【解决方案1】:

您可以通过以下方式在单个查询中执行您想要的操作:

INSERT INTO [CloneConfiguration] 
    SELECT COALESCE(m.maxid + 1, 1), 3, [SourceCCy1Id], [SourceCCy2Id],
           [SourceProviderId], [TargetCCy1Id], [TargetCCy2Id], 
           [TargetProviderId], [Remark]
    FROM [CloneConfiguration] CROSS JOIN
         (SELECT max(id) as maxid FROM CloneConfiguration) m
    WHERE InstrumentId = 2 ;

如果您要插入多行,那么也请使用row_number()

INSERT INTO [CloneConfiguration] 
    SELECT COALESCE(m.maxid, 0) + ROW_NUMBER() OVER (ORDER BY (SELECT NULL)),
           3, [SourceCCy1Id], [SourceCCy2Id],
           [SourceProviderId], [TargetCCy1Id], [TargetCCy2Id], 
           [TargetProviderId], [Remark]
    FROM [CloneConfiguration] CROSS JOIN
         (SELECT max(id) as maxid FROM CloneConfiguration) m
    WHERE InstrumentId = 2 ;

也就是说,正确的解决方案是将 id 定义为 identity 列。然后数据库负责分配一个唯一的 id。您的查询也不会有竞争条件。因此,如果只有一个用户,上述方法可以工作,但如果有多个用户,则可能会失败。

【讨论】:

    【解决方案2】:

    这是假设 sql-server,但我想你还是明白了:

    DECLARE @MAXID INT = (SELECT MAX(Id) FROM [CloneConfiguration]) -- You probably want to number from the highest Id regardless of InstrumentId
    
    INSERT INTO [CloneConfiguration] 
    SELECT @MAXID + ROW_NUMBER() OVER(ORDER BY Id)
    ,      3
    ,      [SourceCCy1Id]
    ,      [SourceCCy2Id]
    ,      [SourceProviderId]
    ,      [TargetCCy1Id]
    ,      [TargetCCy2Id]   
    ,      [TargetProviderId]
    ,      [Remark]
    FROM   [CloneConfiguration] 
    WHERE  InstrumentId=2
    

    思路是先获取表中当前的MAX(Id),然后根据选择的Id添加ROW_NUMBER

    顺便说一下,命名要插入的列也是一个好主意:

    INSERT INTO [CloneConfiguration] (Id, InstrumentId...)
    ...
    

    【讨论】:

    • @MAXID+1 应该这样做..为什么需要row_number
    • @vkp,如果@MAXID = 33,所有选定的记录将以 34 结尾(我假设可以选择超过 1 条记录,如 OP 的示例所示......),这仍然不是独一无二的
    猜你喜欢
    • 1970-01-01
    • 2021-07-03
    • 2015-07-05
    • 2017-08-23
    • 1970-01-01
    • 2017-11-14
    • 1970-01-01
    • 2018-08-06
    相关资源
    最近更新 更多