时不时地,由于以下任何原因,我们不得不将INSERT与UPDATE区分开来感到尴尬:

  • 我们必须至少发表两个声明
  • 我们必须考虑性能
  • 我们必须考虑比赛条件
  • 我们必须在[UPDATE; 如果UPDATE_COUNT = 0 THEN INSERT]和[INSERT; 如果例外然后更新]
  • 我们必须对每个更新/插入的记录执行一次这些语句

总而言之,这是错误和挫败感的重要根源。 同时,使用SQL MERGE语句可能是如此简单!

MERGE的典型情况

在许多其他用例中,在处理多对多关系时,MERGE语句可能会派上用场。 假设我们有以下模式:

CREATE TABLE documents (id NUMBER(7) NOT NULL,CONSTRAINT docu_id PRIMARY KEY (id));CREATE TABLE persons (id NUMBER(7) NOT NULL,CONSTRAINT pers_id PRIMARY KEY (id));CREATE TABLE document_person (docu_id NUMBER(7) NOT NULL,pers_id NUMBER(7) NOT NULL,flag NUMBER(1) NULL,CONSTRAINT docu_pers_pk PRIMARY KEY (docu_id, pers_id),CONSTRAINT docu_pers_fk_docu FOREIGN KEY (docu_id) REFERENCES documents(id),CONSTRAINT docu_pers_fk_pers FOREIGN KEY (pers_id) REFERENCES persons(id));

上表用于模拟哪个人已阅读(flag = 1)/已删除(flag = 2)哪个文档。 为简单起见,通常将“ document_person”实体与“ documents”外部联接,以便“ document-person”记录的存在或不存在可能具有相同的语义:“ flag IS NULL”表示未读文档。
现在,当您要将文档标记为已读时,必须决定是插入一个新的“ document_person”,还是更新现有的“ document_person”。 与删除相同。 与将所有文档标记为已读或删除所有文档相同。

改用MERGE

您可以一口气做到这一切! 假设您要插入/更新一条记录,以将一个文档标记为已读:

-- The target tableMERGE INTO document_person dst-- The data source. In this case, just a dummy recordUSING (SELECT :docu_id as docu_id, :pers_id as pers_id, :flag    as flagFROM DUAL) src-- The merge condition (if true, then update, else insert)ON (dst.docu_id = src.docu_id AND dst.pers_id = src.pers_id)-- The update actionWHEN MATCHED THEN UPDATE SETdst.flag = src.flag-- The insert actionWHEN NOT MATCHED THEN INSERT (dst.docu_id,dst.pers_id,dst.flag)VALUES (src.docu_id,src.pers_id,src.flag)

这看起来很相似,但是比MySQL的INSERT .. ON DUPLICATE KEY UPDATE语句冗长得多,这更加简洁。

发挥到极致

但是,您可以走得更远! 如前所述,您可能还希望将给定人员的所有文档标记为已读。 合并没问题。 如果指定:docu_id,则以下语句与上一条相同。 如果将其保留为空,它将仅将所有文档标记为:flag:

MERGE INTO document_person dst-- The data source is now all "documents" (or just :docu_id) left outer-- joined with the "document_person" mappingUSING (SELECT d.id     as docu_id, :pers_id as pers_id, :flag    as flagFROM documents dLEFT OUTER JOIN document_person d_p ON d.id = d_p.docu_id AND d_p.pers_id = :pers_id-- If :docu_id is set, select only that documentWHERE (:docu_id IS NOT NULL AND d.id = :docu_id)-- Otherwise, select all documentsOR (:docu_id IS NULL)) src-- If the mapping already exists, update. Else, insertON (dst.docu_id = src.docu_id AND dst.pers_id = src.pers_id)-- The rest stays the sameWHEN MATCHED THEN UPDATE SETdst.flag = src.flagWHEN NOT MATCHED THEN INSERT (dst.docu_id,dst.pers_id,dst.flag)VALUES (src.docu_id,src.pers_id,src.flag)

jOOQ中的MERGE支持

jOOQ也完全支持MERGE。 有关更多详细信息,请参见手册(滚动至底部):
http://www.jooq.org/manual/JOOQ/Query/
合并愉快!

参考:我们的JCG合作伙伴 Lukas Eder在JAVA,SQL和JOOQ博客上使用SQL:2003 MERGE语句 编写了 奥术魔术 。

相关文章 :

  • Java中的数据库架构导航
  • ORM问题
  • SQL或NOSQL:这是问题吗?
  • 什么是NoSQL?
  • 按汇总分组/多维数据集

翻译自: https://www.javacodegeeks.com/2011/12/arcane-magic-with-sql2003-merge.html

使用SQL:2003 MERGE语句的奥术魔术相关推荐

  1. merge语句使用_使用SQL:2003 MERGE语句的奥术魔术

    merge语句使用 时不时地,由于以下任何原因,我们不得不将INSERT与UPDATE区分开来感到尴尬: 我们必须至少发表两个声明 我们必须考虑性能 我们必须考虑比赛条件 我们必须在[UPDATE; ...

  2. merge语句_SQL Server MERGE语句概述和示例

    merge语句 In this article, we will review SQL Server MERGE statement, alternatives to MERGE statement, ...

  3. SQL Server - 使用 Merge 语句实现表数据之间的对比同步

    SQL Server - 使用 Merge 语句实现表数据之间的对比同步 原文:SQL Server - 使用 Merge 语句实现表数据之间的对比同步 表数据之间的同步有很多种实现方式,比如删除然后 ...

  4. Oracle中的MERGE语句

    转自http://blog.chinaunix.net/space.php?uid=16981447&do=blog&cuid=430716 做了简单的格式整理,加入了一点点原创的东西 ...

  5. oracle迁移postsql的,osdba's blog : Oracle迁移PostgreSQL系列文章之二:merge语句

    Oracle迁移PostgreSQL系列文章之二:merge语句 Posted on 2015-03-06 11:12:46 by osdba 我们知道,Oracle中有一个特别的merge语句.而P ...

  6. 了解SQL Server CASE语句

    SQL Server CASE statement is equivalent to the IF-THEN statement in Excel. SQL Server CASE语句等效于Excel ...

  7. 【SQL】MERGE

    MERGE可以合并多个表中的数据,也可实现多表中数据的同步.使用MERGE语句对表中数据进行有条件的更新和插入.当查找的行存在时,UPDATE更新行中的数据:当查找的行不存在时,INSERT插入数据. ...

  8. Merge用法:Oracle 10g中对Merge语句的增强

    网址:  http://www.eygle.com/digest/2009/02/mergeoracle_10gmerge.html 在Oracle 10g之前,merge语句支持匹配更新和不匹配插入 ...

  9. Sql serever的语句

    1.Merge语句 假设有两个表名为: source 表和 target 表, 并且需要根据 source 表中匹配的值更新 target 表. 有 三种情况: source 表有一些 target ...

最新文章

  1. java linkedlist底层_手写Java LinkedList核心源码
  2. 第三十四课.模糊神经网络
  3. eclipse从数据库逆向生成Hibernate实体类
  4. JQuery:DOM操作
  5. CCNA学习笔记--静态路由
  6. 数据结构:二分查找算法
  7. 数据相关,资源相关,控制相关的解决方法
  8. 从入门到头秃,2018年机器学习图书TOP10
  9. 二十年前的电脑配置单,大家见过吗?
  10. 190527每日一句,励志| 为了成功,约束自己;有时候“再等等”,就再也等不到了
  11. 接口测试面试题及参考答案(汇总),真香
  12. IAST 实践利用洞态做开源组件的安全治理
  13. 华为OD岗位面试流程及总结
  14. 管理员登陆页面php,Dedecms管理员登录输入账号密码点击登陆又回到登陆界面
  15. matlab实现将彩色图像转换成灰色图像的方法
  16. android 自定义textview圆形,Android 自定义TextView可以设置圆角和按下效果
  17. web、ftp上传区别
  18. IE疑难杂症之已取消网页导航--该站点安全证书的吊销信息不可用
  19. Verilog之条件语句、循环语句、块语句与生成语句
  20. 谈谈对Spring IOC(控制反转)的理解

热门文章

  1. Springboot(十):邮件服务
  2. java无效的源发行版_无效的Java
  3. java获取ram_Java:ChronicleMap第2部分,超级RAM映射
  4. oauth 使用令牌_使用OAuth2令牌的安全REST服务
  5. javadoc 标签_新的Javadoc标签@ apiNote,@ implSpec和@implNote
  6. 高效的企业测试-工作流和代码质量(4/6)
  7. 带有Oracle Digital Assistant和Fn Project的会话式UI。 第二部分
  8. ddl hibernate_Hibernate:DDL模式生成
  9. JVM体系结构101:了解您的虚拟机
  10. Java 9:ServiceLoader