1 个需求,2 种写法, 3 层境界

本文探讨了如何使用SQL的Merge语句优雅地合并用户身份信息,避免了UPDATE/INSERT的潜在冲突,强调了Merge在事务控制和大数据场景下的优势。此外,文章还比较了Merge与传统方法的区别,以及其在性能上的提升。
摘要由CSDN通过智能技术生成

点击蓝色“有关SQL”关注我哟

加个“星标”,天天与10000人一起快乐成长

图 | L

1 个需求

外人看来一个简单的需求:

把某个人的身份信息,合并到用户表里。

思路再简单不过:如果这个人存在表里,那就更新;如果他/她不在,那就新建。

2 种写法

很多朋友,写这类 SQL,手到擒来。无非就是 Update 和 Insert.

先判断下这个人,在不在表里:


IF Exists(SELECT TOP 1 1 FROM User WHERE UserName = @var_UserName)
BEIGN 
    UPDATE User SET XXX = XXX WHERE UserName = @var_UserName
END
ELSE
BEGIN 
    INSERT INTO User ( XXX,XXX) ) VALUES(xxx,xxx)
END 

但,SQL 表达可以更简单,请出今天的主角:Merge

MERGE INTO User
    USING (xxx) AS UserUpdate
    on User.UserName = UserUpdate.UserName
    WHEN MATCHED THEN UPDATE SET UserAddress = UserUpdate.UserAddress
    WHEN NOT MATCHED THEN INSERT(XXX,XXX) VALUES(xxx,xxx)

Merge 语句同样实现了 UPDATE/INSERT 组合的功能。

解释下:

  • USING(xxx) AS UserUpdate ON:

    xxx 表示用来更新的准备数据,其形式可以是一条SELECT 语句,也可以是一条 VALUES构造语句(适用于SQL Server)。

    ON 在这里,指定了匹配条件

  • MATCHED:

    当匹配条件满足,执行数据更新

  • NOT MATCHED :

    当匹配条件不满足,执行数据新建

3 层境界

到这里还没完。

能写出第一类 UPDATE/INSERT 算是基础过关。如果数据库访问量不大,自然没毛病。

但,UPDATE/INSERT 并不安全。

如果在判断 EXISTS 同时,该用户被其他人新建,则会产生冲突。所以,加上 BEGIN TRANS 来发起事务控制,将其他用户操作隔离开来。这是第二境界。

Merge 就不需要这份考量。它是一个语句,从语句层面完成了事务控制。

但 Merge 虽强,碰到大数据量,写法依旧单薄。尤其在 Merge 操作中,更新了上百万行,产生大量日志的同时,还会锁表,对数据库及其不友好。

怎么办?改批次!

 
 MERGE TOP(10000) USER
  USING (xxx) AS UserUpdate
    on User.UserName = UserUpdate.UserName
    WHEN MATCHED THEN UPDATE SET UserName = UserUpdate.UserName
    WHEN NOT MATCHED THEN INSERT(XXX,XXX) VALUES(xxx,xxx)
 

每 10000 条数据做一次 Merge,可以完美解决。

这是第三层考量。

那,为什么要用 Merge 而不用 UPDATE/INSERT 组合呢?原因有 2:

  • Merge 单条语句实现了事务控制,上面已说

  • Merge 是轻量更新:本例用一条数据解释了 Merge,但实际情况,Merge 可以实现表对表的合并,当两表数据量都大时, UPDATE/INSERT  组合,产生了两次对比查询,和两次日志更新,但 Merge 只需一次。

--完--

往期精彩:

本号精华合集(三)

如何写好 5000 行的 SQL 代码

如何提高阅读 SQL 源代码的快感

我在面试数据库工程师候选人时,常问的一些题

零基础 SQL 数据库小白,从入门到精通的学习路线与书单

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dbLenis

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值