2014-02-18 57 views
2

我编写了一个使用MERGE在表中插入/更新数据的过程,但这是我的问题。表中也是主键列的ID列不是IDENTITY列。我找到了一种插入数据的方法,但是我有可能在PK中创建我不想要的空白。批量插入到SQL表中,并使用唯一标识列不是标识

这是我的代码,目前的作品。

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列,因为遗留应用程序仍会将信息插入到该表中,并且如果将其更改为标识列,将会失败。

任何人都可以给我另一种方法来做合并,而不必遍历整个表执行每个更新/插入单独?

+0

'IDENTITY'字段也有差距。这不是你应该关心的问题。 – OGHaza

+1

这个查询不能工作,别名's'和'i'不映射到表 – Andomar

+0

我的错误,我实际上有原始查询的连接。我编辑了问题 – Jaques

回答

0

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

+0

如何排除插入部分中的现有列。添加一个'Col1不在(从表中选择Col1)'? – Jaques

+0

只是省略'当不匹配,然后插入'从第一个查询,并省略'当匹配然后更新'从第二个 – Andomar

+0

它不起作用。插入1并更新其余部分时,ID从10729跳转到21459。总记录数为10729英寸。 – Jaques

0

假设,

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

now inside using, 

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

明白了吗?

+0

这正是我目前的'USING'中发生的情况。如果有更新,它仍然会产生差距 – Jaques