SQL 服务器:UPSERT 事务未到达插入

SQL Server : UPSERT transaction not reaching insert

浏览有关如何创建 "good" 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 单独工作正常。当前脚本只做更新部分

我有一个想法,如果它可以插入它找到的全部数据(因为 select 查询),那么插入才是好的?否则它不会工作。如果是这样,我该如何改进?

我也读过 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通常会失败或运行很长时间(在一些表上,我可以接受,但不好,如果你打算迁移整个数据从一个数据库到另一个数据库)。

我认为这可能不是最佳解决方案。但目前它有效,有什么意见吗?

而不是

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.

您不能像现在这样笼统地检查这个。您必须检查 Table 2 中的每个 ID 是否存在于 Table 1 中。如果存在,则更新 Table 1 否则插入 Table 1。这可以通过以下方式完成。

我们将在 SQL、

中使用 CURSORS 为每个 ID 迭代 Table 2
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