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
浏览有关如何创建 "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 2DECLARE @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