Oracle merge into语句(merge into Statement)

在Oracle中,常规的DML语句只能完成单一功能,,例如insert/delete/update只能三选一,而merge into语句可以同时对一张表进行更新/插入/删除。

目录

一、基本语法

二、用法示例

2.1 同时更新和插入

2.2 where子句

2.3 delete子句

2.4 记录同步错误


、基本语法

merge into常用在数据同步的场景,它会选定一张基表作为数据源,然后与目标表的记录进行匹配,根据匹配的结果,可以对目标表同时进行更新/插入/删除操作。

语法:

MERGE INTO target_table
USING source_table ON (join_condition)
WHEN MATCHED THEN UPDATE SET … [WHERE …] [DELETE … WHERE …]
WHEN NOT MATCHED THEN INSERT (column_list) VALUES (value_list) [WHERE …]
LOG ERRORS INTO … REJECT LIMIT [integer|UNLIMITED]
  • target_table 是要更新的表
  • source_table 是参考表
  • USING … ON () 是两个表的连接条件,用于判断记录是否匹配
  • WHEN MATCHED 对于满足匹配条件的记录进行的操作,可以更新或删除
  • WHEN NOT MATCHED 对于不满足匹配条件的记录,可以插入
  • LOG ERRORS INTO 可以将匹配错误的记录记录到日志表中

二、用法示例

先创建2张表,一张源表,一张目标表:

create table src_table(
id number(6),
name varchar2(32),
salary number(6),
bonus number(6));insert into src_table values(1,'Vincent',1000,100);
insert into src_table values(2,'Victor',2000,200);
insert into src_table values(3,'Grace',3000,300);create table tgt_table(
id number(6),
name varchar2(32),
age number(6),
salary number(6),
bonus number(6));insert into tgt_table values(1,'someone',1,0,0);
insert into tgt_table values(3,'someone',3,0,0);
insert into tgt_table values(4,'someone',4,0,0);
commit;

两张表的数据如下:

Select * from src_table;
Select * from tgt_table;

2.1 同时更新和插入

下面是最基本的用法,利用源表对目标表同时进行更新和插入

merge into tgt_table t
using src_table s on (t.id=s.id)
when matched then update set t.name=s.name, t.salary=s.salary, t.age=10
when not matched then insert values(s.id,s.name,10,s.salary,s.bonus+50);commit;select * from tgt_table;

  • When matched 为匹配存在的记录(id为1,3),更新了name, salary, age个字段
  • When not match 为目标表不存在的记录(id为2),插入了该记录,同时bouns字段加50
  • Matched 和 not matched的子句是独立的,可以任意选择一项,或同时出现
  • 目标表中id为4的记录在源表中不存在(不满足连接条件),因此不会涉及

2.2 where子句

对于匹配的记录,可以使用where子句进一步限制范围

merge into tgt_table t
using src_table s on (t.id=s.id)
when matched then update set t.bonus=s.bonus where s.id>=2;Select * from tgt_table order by id;

  • 这里对匹配的记录bonus字段进行更新,同时进一步限制id>=2的记录才更新
  • Where 子句的条件可以通过源表或者目标表指定,这里是通过源表的s.id指定

2.3 delete子句

在update子句后,还可以跟上delete … where …子句,对匹配上的记录进行删除操作

merge into tgt_table t
using src_table s on (t.id=s.id)
when matched then update set t.bonus=s.bonus+50 where s.id>=3 delete where id>=2;select * from tgt_table order by id;

  • delete where id>=2 指定将ID大于等于2的记录删除,但注意id为2的记录并未被删除,只有3被删除了
  • 因为delete只会在update匹配的到记录范围内删除,update子句有个where s.id>=3,delete也会受到这个条件的限制
  • 实际执行的效果是 delete where s.id>=3 and id>=2,只有id为3的记录满足这个条件
  • id为4的记录不在匹配范围内,不受merge into语句的影响,也不会被删除

2.4 记录同步错误

数据同步的时,源表和目标表的结构/数据类型/约束可能并不一致,这就导致数据同步可能部分失败,现在我们修改tgt表,限制salary字段值不能超过3000,即插入超过3000的数字将失败:

Alter table tgt_table modify salary number(6) check(salary<=3000);

首先调用dbms_errlog.create_error_log为tgt_table创建一张错误日志表,表名为errlog:

exec dbms_errlog.create_error_log('tgt_table', 'errlog');

  • 第一个参数指定要创建错误日志的基表,第二个参数是错误日志表名

然后在执行merge into 语句时,在最后跟上log errors into子句,如果语句执行过程中遇到错误,则会将错误记录到错误日志中,方便后期排查和修复,这里将tgt_table清空,尝试将src_table的3条数据同步进去,同时salary增加1000

truncate table tgt_table;merge into tgt_table t
using src_table s on (t.id=s.id)
when not matched then insert values(s.id,s.name,10,s.salary+1000,s.bonus)
log errors into errlog('something is wrong.');select * from tgt_table;

  • 这里将tgt_table表清空,然后尝试将src_table中的3条记录同步进来,同步过程中我们将salary增加了1000
  • 因为tgt_table表salary有约束不能超过3000,因此语句回滚,一条记录都没同步进来
  • errlog中的'something is wrong.' 是用户定义的错误标记,可以帮助识别是哪个语句导致的错误

查询errlog表,可以看到导致失败的原因,id为3的记录,salary在增加1000后为4000,违反了目标表的约束(check salary<=3000):

select * from errlog;

如果我们不想让出现错误的时候语句就回滚,可以在后面跟上一个reject limit N子句,限制只有出现N个以上的错误时才回滚语句:

merge into tgt_table t
using src_table s on (t.id=s.id)
when not matched then insert values(s.id,s.name,10,s.salary+1000,s.bonus)
log errors into errlog('Allow one error.') reject limit 1;select * from tgt_table;

  • 我们在上面的语句后面增加了1个reject limit 1子句,当出现1个及以下的错误时,并不会回滚
  • 因此id为1和2的记录成功插入,语句并未报错
  • errlog的用户标记修改为'Allow one error.'

再次查询errlog

select * from errlog;

  • 通过Allow one error标签,我们发现ID为3的记录因违反约束没有被插入
  • 但这此有reject limit 1子句,语句允许出现1个及以下错误,因此满足条件的记录被成功插入
  • 如果选择reject limit unlimited,则不限制错误数量

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/200939.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Gitee项目推荐-HasChat

最近由于使用的局域网通信工具总是出问题&#xff0c;就在考虑有没有好的替代品。搜索了一番&#xff0c;发现这个还不错&#xff1a; HasChat: 一款极简聊天应用&#xff0c;比较完整&#xff0c;略好看 页面简洁&#xff0c;功能也比较齐全&#xff0c; 感兴趣的小伙伴可以…

【Redis】redis 高性能--线程模型以及epoll网络框架

目录 一.前言 二.多线程的弊端 2.1 锁的开销问题 2.2 多线程上下文切换带来的额外开销 2.3 多线程占用内存成本增高 三.基本IO模型与epoll 模式 3.1 基本IO模型 3.2 单线程处理机制 四.总结 一.前言 我们经常讨论到&#xff0c;redis 是单线程&#xff0c;那为什么单线…

sizeof()、strlen()、length()、size()的区别(笔记)

​ 上面的笔记有点简陋&#xff0c;可以看一下下面这个博主的&#xff1a; c/c中sizeof()、strlen()、length()、size()详解和区别_csize,sizeof,length_xuechanba的博客-CSDN博客

the name of a constructor must match the name of the enclosing class

构造器名匹配封闭类名 命令码的位置关系不对 解决&#xff1a;调整 命令码所在层级

xxljob学习笔记02(小滴课堂)

分布式调度参数传递和调度日志配置讲解 可以设置任务参数。 代码层面&#xff1a; 可以这样传递参数。 我们在xxljob页面去设置参数&#xff1a; 我们执行一次任务&#xff1a; 我们这里就拿到了参数。 这样我们就能拿到参数了。 日志打印&#xff1a; 在代码中也可以实现&…

GPT-Crawler一键爬虫构建GPTs知识库

GPT-Crawler一键爬虫构建GPTs知识库 写在最前面安装node.js安装GPT-Crawler启动爬虫结合 OpenAI自定义 assistant自定义 GPTs&#xff08;笔者用的这个&#xff09; 总结 写在最前面 GPT-Crawler一键爬虫构建GPTs知识库 能够爬取网站数据&#xff0c;构建GPTs的知识库&#xf…

npm : 无法加载文件 D:\nodejs\node_global\npm.ps1,因为在此系统上禁止运行脚本。

今天在使用vscode下载项目的依赖时&#xff0c;输入 pnmp install,结果报错: npm : 无法加载文件 D:\nodejs\node_global\npm.ps1&#xff0c;因为在此系统上禁止运行脚本。原因&#xff1a; 因为在此系统上禁止运行脚本&#xff0c;也就是说没有权限&#xff0c;查一下&#…

CoreDNS实战(十一)-分流与重定向

本文主要介绍了目前CoreDNS服务在外部域名递归结果过程中出现的一些问题以及使用dnsredir插件进行分流和alternate插件进行重试优化的操作。 1 自建DNS服务现状 一般来说&#xff0c;无论是bind9、coredns、dnsmasq、pdns哪类dns服务器&#xff0c;我们自建的监听在UDP53端口…

AI 绘画 | Stable Diffusion LCM和FP8 显存不足的福音

前言 在我们使用Stable Diffusion 作画的时候,普通用户因为电脑显存配置过低,经常会出现爆显存和出图慢的困扰。而SD-WebUI在显存优化方便不如ComfyUI和Fooocus,但是也有一些弥补SD-WebUI显存问题的方案,那就是LCM和FP8。 LCM 教程 简介 LCM 是一个用于 Stable Diffusio…

[组合数学]LeetCode:2954:统计感冒序列的数目

作者推荐 [二分查找]LeetCode2040:两个有序数组的第 K 小乘积 题目 给你一个整数 n 和一个下标从 0 开始的整数数组 sick &#xff0c;数组按 升序 排序。 有 n 位小朋友站成一排&#xff0c;按顺序编号为 0 到 n - 1 。数组 sick 包含一开始得了感冒的小朋友的位置。如果位…

Python下TCP编程

​ 在Python中使用socket模块的socket函数可以完成&#xff0c;语法格式如下&#xff1a; ssocket.socket(AddressFamily, Type)函数socket.socket创建一个socket&#xff0c;返回该socket的描述符。该函数带有两个参数。 Address Family&#xff1a;可以选择AF_INET&#xf…

Kafka 消费者 API 指南:深入探讨消费者的实现与最佳实践

Kafka 消费者 API 是连接应用程序与 Kafka 集群之间的关键接口&#xff0c;用于从 Kafka 主题中拉取消息并进行处理。本篇文章将深入探讨 Kafka 消费者 API 的核心概念、用法&#xff0c;以及一些最佳实践&#xff0c;帮助你构建高效、可靠的消息消费系统。 1. Kafka 消费者 A…

根据字符出现频率排序 (哈希表,map,cmp,sort,遍历)

它要我们统计每个字符出现的个数&#xff0c;所以会想到使用map有一个键值对&#xff0c;一个key为char类型&#xff0c;一个value为int类型&#xff0c;这样我们可以得到每个字符的出现次数&#xff0c;又因为它让出现次数多的先输出&#xff0c;所以会想到使用sort从大到小排…

Python查看文件列表

os.listdir 是 Python 的一个内置函数&#xff0c;用于列出指定目录中的所有文件和子目录。它接受一个字符串参数&#xff0c;即要列出内容的目录的路径。 列出当前工作目录中的所有文件和子目录 files_and_dirs os.listdir() print(files_and_dirs) 列出指定目录中的所…

<Linux>(极简关键、省时省力)《Linux操作系统原理分析之文件管理(3)》(24)

《Linux操作系统原理分析之文件管理&#xff08;3&#xff09;》&#xff08;24&#xff09; 7 文件管理7.5 文件存储空间的管理7.6 文件的共享和保护7.6.1 文件存取控制7.6.2 文件共享的实现方法7.6.3 文件的备份转储 7 文件管理 7.5 文件存储空间的管理 位示图 对每个磁盘…

【S32K3环境搭建】-0.1-安装S32 Design Studio for S32 Platform 3.5

目录&#xff08;S32DS安装步骤详细&#xff09; 1 安装S32 Design Studio for S32 Platform 3.5准备工作 2 下载S32 Design Studio for S32 Platform 3.5安装包 2.1 获取S32DS的License许可 3 安装S32 Design Studio for S32 Platform 3.5 4 打开S32 Design Studio for S…

uniapp基于u-grid-item九宫格实现uCharts秋云图表展示

uniapp基于uView的UI组件u-grid-item九宫格实现uCharts秋云可视化图表展示 这里使用uView的u-grid-item九宫格组件去显示图标排列 九宫格可以做成多列&#xff0c;移动设备上可以通过左右滑动进行展示 <template><div><div style"text-align: center;font…

Apollo新版本Beta技术沙龙

有幸参加Apollo开发者社区于12月2日举办的Apollo新版本(8.0)的技术沙龙会&#xff0c;地址在首钢园百度Apollo Park。由于去的比较早&#xff0c;先参观了一下这面的一些产品&#xff0c;还有专门的讲解&#xff0c;主要讲了一下百度无人驾驶的发展历程和历代产品。我对下面几个…

正则表达式(4):连续次数的匹配

正则表达式&#xff08;4&#xff09;&#xff1a;连续次数的匹配 小结 本博文转载自 在本博客中&#xff0c;”正则表达式”为一系列文章&#xff0c;如果你想要从头学习怎样在Linux中使用正则&#xff0c;可以参考此系列文章&#xff0c;直达链接如下&#xff1a; 在Linux中…

C语言进阶之路-指针、数组等混合小boss篇

目录 一、学习目标&#xff1a; 二、指针、数组的组合技能 引言 指针数组 语法 数组指针 三、勇士闯关秘籍 四、大杂脍 总结 一、学习目标&#xff1a; 知识点&#xff1a; 明确指针数组的用法和特点掌握数组指针的用法和特点回顾循环等小怪用法和特点 二、指针、数…