暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

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

有关SQL 2021-01-22
477

点击蓝色“有关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_UserNameENDELSEBEGIN     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 数据库小白,从入门到精通的学习路线与书单



文章转载自有关SQL,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论