sql-server - SQL Server 基于连接 2 个表的更新和插入
问题描述
我有 2 个完全相同的表:table1 (a, b, c) 和 table2 (a, b, c)
但是每晚t2
都会更新,在更新之后,我想加入这两个表,如果该行存在于t1
,则更新t1.b
,但如果不存在,则将该行插入t2
到t1
。
我知道这行得通,因为它是选择的
SELECT
(CASE
WHEN t1.a IS NOT NULL
THEN t1.b + t2.b
ELSE t2.b
END) AS 'total new amount'
FROM
table1 t1
RIGHT JOIN
table2 t2 ON t2.a = t1.a AND t2.c = t1.c
但是我怎样才能进行更新和插入呢?
更新:
所以我想我必须使用 MERGE 命令
MERGE table1 as t1
USING table2 as t2
ON (t1.a = t2.a AND t1.c = t2.c )
when MATCHED T
HEN UPDATE SET t1.b = t1.b + t2.b
when NOT MATCHED
THEN insert (a,b,c) VALUES (t2.a,t2.b,t2.c);
但现在我收到了这个错误:
MERGE 语句多次尝试更新或删除同一行。当目标行匹配多个源行时会发生这种情况。MERGE 语句不能多次 UPDATE/DELETE 目标表的同一行。优化 ON 子句以确保目标行最多匹配一个源行,或使用 GROUP BY 子句对源行进行分组。
我在这里做错了什么?
提前致谢
解决方案
但是每天晚上,t2 都会更新,在更新之后,我想加入这两个表,如果该行存在于 t1 中,则更新 t1.b,但如果不存在,则将 t2 中的行插入 t1。
t1有什么事吗?
如果没有任何变化t1
,同步表的最简单方法就是截断并重新加载
根据表中的记录数和更改率,这可能比执行 upsert 更快或更慢。
TRUNCATE TABLE T1;
INSERT INTO T1 (Col1,Col2,Col3)
SELECT Col1,Col2,Col3 FROM T2;
根据使用 T1 的频率,有一些方法可以使最终用户透明。(即他们永远不会看到一张空桌子)
一些方法是:
- 使用快照隔离和事务
- 使用临时表和
SWITCH PARTITION
https://littlekendra.com/2017/01/19/why-you-should-switch-in-staging-tables-instead-of-renaming/ - 使用临时表和
sp_rename
MERGE
当然是进行 upsert 但单独的一种方法,INSERT
并且UPDATE
语句通常更容易调试和执行得更好。
推荐阅读
- swift - 如何修复“imagePickerController”无法选择照片?
- javascript - 如何组合来自两个 API 端点的数据?
- c - 修改跳转行代码的函数返回地址
- java - 具有独立客户端特定隔离的 Spring Boot 多租户代码
- javascript - 检查某些内容是否不为空后,我得到一个空或未定义的类型错误。如何?
- android - 如何使用方法将编辑文本的数据发送到其他活动
- oracle - 从未输入 FORALL 时的 FORALL 和 sql%rowcount
- backup - 在 cpanel 备份中从 cpbackup-exclude.conf 中排除“备份”之类的名称
- django - 我看不到 Cathegory 列表管理员,如何解决
- python - 变量列表在列表中创建列表