【问题标题】:Bulk Insert into SQL Table with unique ID column that is not Identity使用不是标识的唯一 ID 列批量插入 SQL 表
【发布时间】:2014-02-18 10:06:13
【问题描述】:

我编写了一个使用MERGE 在表中插入/更新数据的过程,但这是我的问题。表上的ID 列也是主键列不是IDENTITY 列。我找到了一种插入数据的方法,但可能会在 PK 中产生我不想要的间隙。

这是我目前有效的代码。

MERGE Table p 
USING (SELECT i.Col1, 
              i.Col2, 
              i.Col3, 
              (SELECT ISNULL(MAX(ID), 0) FROM Table1 i) +
                  ROW_NUMBER() OVER (ORDER BY ID) ID
      ) a(Col1, Col2, Col3, ID)
ON p.Col1 = a.Col1
WHEN MATCHED THEN UPDATE set p.Col2 = a.Col2, p.Col3 = a.Col3
WHEN NOT MATCHED THEN INSERT (ID, Col1, Col2, Col3)
VALUES (a.ID, a.Col1, a.Col2, a.Col3)

ROW_NUMBER() OVER (ORDER BY ID) 将为我提供唯一值,但如果 20 条记录中有 10 条被更新,它将在我的 ID 列中的其他插入中产生间隙。

我试过了

(Select ISNULL(MAX(ID), 0) + 1 from Table)

但显然只有在插入 1 条记录时才能正常工作。批量操作不会为每个插入语句执行子查询,这会导致 PK 违规。

我无法将 ID 列更改为 identity 列,因为旧版应用程序仍会将信息插入到该表中,如果我将其更改为标识列将会失败。

谁能给我另一种合并方式,而不必遍历整个表并分别执行每个更新/插入?

【问题讨论】:

  • IDENTITY 字段也有空白。这不是您应该担心的问题。
  • 此查询无效,别名si 未映射到表
  • 我的错误,我实际上在原始查询上有一个联接。我已经编辑了问题
  • @OGHaza 的问题是它们可以从具有 10k + 记录的表(示例中的 Table1)合并,它可能会在两个 ID 之间产生 10k 的间隙
  • @Jaques,它可以工作。首先在合并之前获得最大值。然后以某种方式在内部使用这个 Max 变量值来增加一个。虽然我正在尝试自己。有什么问题吗?

标签: sql-server merge


【解决方案1】:

一个简单的解决方案是分两步合并。在第一步中,更新现有行。在第二步中,插入新行。这避免了间隙问题,因为第二步只插入。

【讨论】:

  • 如何在插入部分排除现有列。添加where Col1 not in (Select Col1 from Table)?
  • 第一个查询省略when not matched then insert,第二个查询省略when matched then update
  • 它不起作用。当插入 1 并更新其余部分时,ID 从 10729 跳转到 21459。总记录数为 10729 英寸。
  • 对,我猜你确实需要一个where not exists 子查询。你想要一个这样的例子吗?
【解决方案2】:

假设,

Declare @Max int
select @max=isnull(id,0) from table2

now inside using,

      select * ,@Max +ROW_NUMBER()over(order by (select 0))
      from Table2

知道了吗?

【讨论】:

  • 这正是我当前的USING 中发生的事情。如果有更新,它仍然会造成差距
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多