SQL Server:UPSERT事务未到达插入

时间:2016-05-16 12:00:06

标签: sql sql-server insert-update upsert

浏览有关如何创建“好”UPSERT语句shown here的各种示例,我创建了以下代码(我更改了列名称):

BEGIN TRANSACTION

IF EXISTS (SELECT *
           FROM Table1 WITH (UPDLOCK, SERIALIZABLE), Table2
           WHERE Table1.Data3 = Table2.data3)
BEGIN
    UPDATE Table1
    SET Table1.someColumn = Table2.someColumn,
        Table1.DateData2 = GETDATE()
    FROM Table1
    INNER JOIN Table2 ON Table1.Data3 = Table2.data3
END
ELSE
BEGIN
    INSERT INTO Table1 (DataComment, Data1, Data2, Data3, Data4, DateData1, DateData2)
        SELECT  
            'some comment', data1, data2, data3, data4, GETDATE(), GETDATE()
        FROM 
            Table2
END

COMMIT TRANSACTION

我的问题是,它永远不会发生INSERT部分。 INSERT单独工作正常。当前脚本仅执行更新部分。

我知道插入只是好的,如果它可以插入它找到的整个数据(因为选择查询)?否则它将无法工作。如果是这样,我该如何改进呢?

我还阅读了MERGE条款,并希望避免使用它。

//编辑:

在尝试了几个在互联网上找到的样本并在这里解释之后,我重新做了如下逻辑:

BEGIN TRANSACTION
    BEGIN
        UPDATE table1
        SET something
        WHERE condition is met 

        UPDATE table2
        SET helpColumn = 'DONE'
        WHERE condition is met
    END
    BEGIN
        INSERT INTO table1(data)
        SELECT data
        FROM table2
        WHERE helpColumn != 'DONE'
    END
COMMIT TRANSACTION

尝试其他解决方案时,INSERT通常会失败或运行很长时间(在几张桌子上,我可以接受,但不好,如果您计划将整个数据从一个数据库迁移到另一个数据库)。

我认为这可能不是最好的解决方案。但是现在它有效,有什么意见吗?

2 个答案:

答案 0 :(得分:0)

而不是

if (something )
update query
else 
insert query

像这样构建你的逻辑:

update yourTable
etc
where some condition is met

insert into yourTable
etc
select etc
where some condition is met.

答案 1 :(得分:0)

一般情况下,你不能像往常那样检查这个。如果表1中存在,则必须检查表2中的每个ID。如果存在,则更新表1,否则插入表1.这可以通过以下方式完成。

我们将使用SQL中的CURSORS

在表2中针对每个ID进行迭代
DECLARE @ID int
DECLARE mycursor CURSOR 
FOR
SELECT ID FROM Table2 FORWARD_ONLY  --Any Unique Column

OPEN mycursor 
FETCH NEXT FROM mycursor
INTO @ID

WHILE @@FETCH_STATUS = 0
BEGIN

IF EXISTS (SELECT 1 FROM Table1 WHERE ID = @ID)
  UPDATE t1 SET t1.data= T2.data  --And whatever else you want to update
  FROM
  Table1 t1
  INNER JOIN 
  Table2 t2
  ON t1.ID = t2.ID --Joining column
  WHERE t1.id = @ID
ELSE
  INSERT INTO Table1
  SELECT * FROM Table2 WHERE ID = @ID

FETCH NEXT FROM mycursor
INTO @ID
END
CLOSE mycursor
DEALLOCATE mycursor