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