Oracle MySQL相关工具replace操作实现方式区别

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 本文列举MySQL、Oracle、常用数据导入工具碰到主键冲突、唯一约束、以及其他对重复数据、已有数据的处理区别,并介绍MySQL、Oracle replace相关语句实现区别。由此可见在实际使用不同数据库过程中,还是有许多差别,需要大家细心留意。

数据导入工具中的replace

1,oracle impdp 导入数据的表已存在指定TABLE_EXISTS_ACTION参数,如果目标库存在相同名称的表,执行下面的操作

1) skip:默认跳过这张表,继续下一个对象。如果CONTENT设置了DATA_ONLY参数,则默认值为append。
2) replace:先drop表,然后创建表,最后插入数据
3) append:在原来数据的基础上增加数据
4) truncate:先truncate,然后再插入数据

2,oracle sqlloader 加载数据模式,遇到有数据时

1) APPEND //原先的表有数据 就加在后面
2) INSERT // 装载空表 如果原先的表有数据 sqlloader会停止 默认值
3) REPLACE // 原先的表有数据 原先的数据会全部删除
4) TRUNCATE // 指定的内容和replace的相同 会用truncate语句删除现存数据

3,mysql load data 加载数据 对有唯一键记录重复时

1)如果指定replace,新行将代替有相同的唯一键值的现有行。具体逻辑同mysql数据库内replace into语句
2)如果指定ignore,跳过有唯一键的现有行的重复行的输入。
3)如果不指定任何一个选项,当找到重复键时,出现一个错误,并且文本文件的余下部分被忽略。

4,DataX工具

导入数据碰到主键或唯一键冲突:选择导入模式,可以支持 insert/replace/insert ignore 方式

insert 指当主键/唯一性索引冲突,数据集成视为脏数据进行处理。
replace 指没有遇到主键/唯一性索引冲突时,与 insert 行为一致,当主键/唯一性索引冲突时会用新行替换原有行所有字段。
insert ignore 指当主键/唯一性索引冲突,数据集成将直接忽略更新丢弃,并且不记录!

注意

MySQL writer支持replace into,参考MySQL数据库的replace into语句。

Oracle writer不支持replace into,支持insert into...(当主键/唯一性索引冲突时会写不进去冲突的行),因为Oracle不支持replace、replace into语句。OracleWriter和MysqlWriter不同,不支持配置writeMode参数。原因可见文末

数据库中的replace

1,MySQL数据库中的replace、replace into语句

replace在没有碰到主键、唯一索引重复值时,和insert完全相同。因此replace仅当表具有PRIMARY KEY或 UNIQUE索引时才有意义。
如果表中的旧行与a PRIMARY KEY或UNIQUE 索引的新行具有相同的值, 则在插入新行之前删除该旧行。

要使用REPLACE,您必须同时拥有表的INSERT和 DELETE特权。

MySQL对REPLACE(和 LOAD DATA ... REPLACE)使用以下算法 :

  1. 尝试将新行插入表中
  2. 虽然插入失败是因为主键或唯一索引发生重复键错误:
    • 从表中删除具有重复键值的冲突行
    • 再试一次将新行插入表中
mysql> select * from replace1;
+----+-------+
| id | name  |
+----+-------+
|  1 | aaa   |
|  2 | wang1 |
|  3 | ccc   |
+----+-------+
3 rows in set (0.00 sec)

mysql> replace into replace1 values (3,'ccc');
Query OK, 1 row affected (0.02 sec)

mysql> replace into replace1 values (3,'ccc');
Query OK, 1 row affected (0.01 sec)

mysql> replace into replace1 values (3,'ddd');
Query OK, 2 rows affected (0.00 sec)

mysql> replace into replace1 values (3,'ddd');
Query OK, 2 rows affected (0.00 sec)

mysql> replace replace1 values (3,'ddd');
Query OK, 1 row affected (0.00 sec)

mysql> replace replace1 values (3,'ccc');
Query OK, 2 rows affected (0.01 sec)

从执行结果来看,replace和replace into 具有相同的作用。

也可以使用MySQL help命令查看帮助:

mysql> help replace;

2,MySQL数据库的INSERT ... ON DUPLICATE KEY UPDATE语句

insert into UNE_CBILL_PRINT_CLOUD(fid,feinvoicecode,ftype)VALUES('1','1','1')
        ON DUPLICATE KEY UPDATE foperator = '1',ftype = '3';

replace into 效率比较低,因为在更新数据的时候,要先删除旧的,然后插入新的,在这个过程中,还要重新维护索引;

insert on duplicate 的更新操作虽然也会更新数据,但其对主键的索引却不会有改变,也就是说,insert on duplicate 更新对主键索引没有影响,因此对索引的维护成本就低了一些。

相关测试:

mysql> 
mysql> create table replace1(id int primary key,name varchar(8));
Query OK, 0 rows affected (0.21 sec)

mysql> 
mysql> 
mysql> 
mysql> create unique index unique_name on replace1(name);
Query OK, 0 rows affected (0.37 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> 
mysql> 
mysql> 
mysql> insert into replace1 values(1,'aaa');
Query OK, 1 row affected (0.00 sec)

mysql> 
mysql> 
mysql> 
mysql> replace into replace1 values(2,'bbb');
Query OK, 1 row affected (0.01 sec)

mysql> 
mysql> 
mysql> 
mysql> replace into replace1 values(3,'ccc');
Query OK, 1 row affected (0.00 sec)

mysql> 
mysql> 
mysql> replace into replace1 values(3,'ccc');
Query OK, 2 rows affected (0.01 sec)

mysql> replace into replace1 values(3,'ccc');
Query OK, 2 rows affected (0.00 sec)

mysql> 
mysql> select * from replace1;
+----+------+
| id | name |
+----+------+
|  1 | aaa  |
|  2 | bbb  |
|  3 | ccc  |
+----+------+
3 rows in set (0.00 sec)

mysql> 
mysql> 
mysql> replace into replace1 values(4,'ccc');
Query OK, 2 rows affected (0.01 sec)

mysql> 
mysql> 
mysql> 
mysql> select * from replace1;
+----+------+
| id | name |
+----+------+
|  1 | aaa  |
|  2 | bbb  |
|  4 | ccc  |
+----+------+
3 rows in set (0.00 sec)

mysql> 
mysql> replace into replace1 values(3,'ccc');
Query OK, 2 rows affected (0.01 sec)

mysql> 
mysql> 
mysql> select * from replace1;
+----+------+
| id | name |
+----+------+
|  1 | aaa  |
|  2 | bbb  |
|  3 | ccc  |
+----+------+
3 rows in set (0.00 sec)

mysql> 
mysql> desc replace1;
+-------+------------+------+-----+---------+-------+
| Field | Type       | Null | Key | Default | Extra |
+-------+------------+------+-----+---------+-------+
| id    | int(11)    | NO   | PRI | NULL    |       |
| name  | varchar(8) | YES  | UNI | NULL    |       |
+-------+------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

mysql> 
mysql> 
mysql> 
mysql> replace into replace1 values(4,'ddd');
Query OK, 1 row affected (0.00 sec)

mysql> 
mysql> 
mysql> select * from replace1;
+----+------+
| id | name |
+----+------+
|  1 | aaa  |
|  2 | bbb  |
|  3 | ccc  |
|  4 | ddd  |
+----+------+
4 rows in set (0.00 sec)

mysql> 
mysql> replace into replace1 values(4,'ccc');
Query OK, 3 rows affected (0.01 sec)

mysql> 
mysql> 
mysql> select * from replace1;
+----+------+
| id | name |
+----+------+
|  1 | aaa  |
|  2 | bbb  |
|  4 | ccc  |
+----+------+
3 rows in set (0.00 sec)

mysql> 
mysql> 
mysql> 
mysql> 
mysql> replace into replace1 values(3,'ccc');
Query OK, 2 rows affected (0.00 sec)

mysql> 
mysql> 
mysql> 
mysql> select * from replace1;
+----+------+
| id | name |
+----+------+
|  1 | aaa  |
|  2 | bbb  |
|  3 | ccc  |
+----+------+
3 rows in set (0.01 sec)

mysql> 
mysql> 
mysql> 
mysql> replace into replace1 values(3,'ccc');
Query OK, 2 rows affected (0.01 sec)

mysql> 
mysql> 
mysql> 
mysql> drop index unique_name;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
mysql> 
mysql> 
mysql> 
mysql> help drop index 
Name: 'DROP INDEX'
Description:
Syntax:
DROP INDEX index_name ON tbl_name
    [algorithm_option | lock_option] ...

algorithm_option:
    ALGORITHM [=] {DEFAULT|INPLACE|COPY}

lock_option:
    LOCK [=] {DEFAULT|NONE|SHARED|EXCLUSIVE}

DROP INDEX drops the index named index_name from the table tbl_name.
This statement is mapped to an ALTER TABLE statement to drop the index.
See [HELP ALTER TABLE].

To drop a primary key, the index name is always PRIMARY, which must be
specified as a quoted identifier because PRIMARY is a reserved word:

DROP INDEX `PRIMARY` ON t;

URL: http://dev.mysql.com/doc/refman/8.0/en/drop-index.html


mysql> 
mysql> 
mysql> 
mysql> drop index unique_name on replace1;
Query OK, 0 rows affected (0.03 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> 
mysql> 
mysql> 
mysql> replace into replace1 values(3,'ccc');
Query OK, 1 row affected (0.01 sec)

mysql> 
mysql> 
mysql> replace into replace1 values(3,'ccc');
Query OK, 1 row affected (0.01 sec)

mysql> 
mysql> 
mysql> insert into replace1 values(4,'ddd');
Query OK, 1 row affected (0.01 sec)

mysql> create unique index unique_name on replace1(name);
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> insert into replace1 values(5,'eee');
Query OK, 1 row affected (0.01 sec)

mysql> 
mysql> desc replace1;
+-------+------------+------+-----+---------+-------+
| Field | Type       | Null | Key | Default | Extra |
+-------+------------+------+-----+---------+-------+
| id    | int(11)    | NO   | PRI | NULL    |       |
| name  | varchar(8) | YES  | UNI | NULL    |       |
+-------+------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

mysql> 
mysql> 
mysql> update replace1 set name='ccc' where id=3;
Query OK, 0 rows affected (0.00 sec)
Rows matched: 1  Changed: 0  Warnings: 0

mysql> update replace1 set name='ccc' where id=3;
Query OK, 0 rows affected (0.00 sec)
Rows matched: 1  Changed: 0  Warnings: 0

mysql> 
mysql> 
mysql> update replace1 set name='ddd' where id=3;
ERROR 1062 (23000): Duplicate entry 'ddd' for key 'unique_name'
mysql> 
mysql> 
mysql> update replace1 set name='www' where id=3;
Query OK, 1 row affected (0.03 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> 
mysql> 
mysql> update replace1 set name='ccc' where id=3;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> 
mysql> update replace1 set name='ccc' where id=3;
Query OK, 0 rows affected (0.00 sec)
Rows matched: 1  Changed: 0  Warnings: 0

mysql> 
mysql> update replace1 set name='ccc' where id=3;
Query OK, 0 rows affected (0.00 sec)
Rows matched: 1  Changed: 0  Warnings: 0

注意:

1,在有多个唯一索引的时候执行replace操作会出现一些奇怪的现象,如除主键外,还有个唯一索引。replace操作影响了2行,所以先删掉冲突的2行,并进行插入一行,返回提示影响了3行数据,replace一条数据,表的总行数少了一条。

2,除主键外有其他唯一索引时,replace语句values如果完全相同时,影响行数为2,是先delete再insert,当仅有主键没有其他唯一索引时,影响行数是1,但实际没有做delete操作(类似于update完全相同值的场景),上述推测根据binlog分析的,再深入可能得根据MySQL源码分析。

由此得出以下2个结论:

当有多个唯一索引时会多删除数据,慎用replace,同时也尽量避免这种情形,满足数据库设计的第二范式。
只有一个主键or唯一索引的情况,可以使用insert on duplicate 操作,比replace操作性能好一些,减少对索引维护带来的性能开销。

3,Oracle数据库中对应的实现是merge into语句

MERGE INTO --要插入的表 别名
USING (

  --查询的SQL
  )别名 ON 
     --(连接条件)

WHEN MATCHED THEN --如果符合条件

 UPDATE SET 

WHEN NOT MATCHED THEN

 INSERT ()VALUES();--不符合就插
/*语法:
MERGE [INTO [schema .] table [t_alias]
USING [schema .] { table | view | subquery } [t_alias]
ON ( condition )
WHEN MATCHED THEN merge_update_clause
WHEN NOT MATCHED THEN merge_insert_clause;
*/

Oracle数据库没有和MySQL一样的replace into语句,
但是有merge into 语句,可以同时实现update和insert的功能。
update子句后面可以跟delete子句来去掉一些不需要的行
delete只能和update配合,从而达到删除满足where条件的子句的记录

Oracle 的 merge into 语句的insert、update、delete互相配合能达到跟MySQL replace语句一样的效果。
由于没有根据唯一约束重复值进行操作的replace,因此datax oracle writer不支持配置writeMode参数。

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
2月前
|
存储 Oracle 关系型数据库
Oracle和MySQL有哪些区别?从基本特性、技术选型、字段类型、事务、语句等角度详细对比Oracle和MySQL
从基本特性、技术选型、字段类型、事务提交方式、SQL语句、分页方法等方面对比Oracle和MySQL的区别。
327 18
Oracle和MySQL有哪些区别?从基本特性、技术选型、字段类型、事务、语句等角度详细对比Oracle和MySQL
|
2月前
|
Oracle NoSQL 关系型数据库
主流数据库对比:MySQL、PostgreSQL、Oracle和Redis的优缺点分析
主流数据库对比:MySQL、PostgreSQL、Oracle和Redis的优缺点分析
194 2
|
28天前
|
Oracle 关系型数据库 MySQL
shell获取多个oracle库mysql库所有的表
请注意,此脚本假设你有足够的权限访问所有提到的数据库。在实际部署前,请确保对脚本中的数据库凭据、主机名和端口进行适当的修改和验证。此外,处理数据库操作时,务必谨慎操作,避免因错误的脚本执行造成数据损坏或服务中断。
38 0
|
3月前
|
SQL 关系型数据库 MySQL
在 MySQL 中使用 `REPLACE` 函数
【8月更文挑战第8天】
820 7
在 MySQL 中使用 `REPLACE` 函数
|
3月前
|
Oracle 关系型数据库 MySQL
Mysql和Oracle数据库死锁查看以及解决
【8月更文挑战第11天】本文介绍了解决MySQL与Oracle数据库死锁的方法。MySQL可通过`SHOW ENGINE INNODB STATUS`查看死锁详情,并自动回滚一个事务解除死锁;也可手动KILL事务。Oracle则通过查询V$LOCK与V$SESSION视图定位死锁,并用`ALTER SYSTEM KILL SESSION`命令终止相关会话。预防措施包括遵循ACID原则、优化索引及拆分大型事务。
108 3
|
4月前
|
SQL Oracle 关系型数据库
关系型数据库Oracle备份工具
【7月更文挑战第19天】
77 4
|
4月前
|
SQL Oracle 关系型数据库
MySQL、SQL Server和Oracle数据库安装部署教程
数据库的安装部署教程因不同的数据库管理系统(DBMS)而异,以下将以MySQL、SQL Server和Oracle为例,分别概述其安装部署的基本步骤。请注意,由于软件版本和操作系统的不同,具体步骤可能会有所变化。
259 3
|
18天前
|
存储 SQL 关系型数据库
Mysql学习笔记(二):数据库命令行代码总结
这篇文章是关于MySQL数据库命令行操作的总结,包括登录、退出、查看时间与版本、数据库和数据表的基本操作(如创建、删除、查看)、数据的增删改查等。它还涉及了如何通过SQL语句进行条件查询、模糊查询、范围查询和限制查询,以及如何进行表结构的修改。这些内容对于初学者来说非常实用,是学习MySQL数据库管理的基础。
78 6
|
16天前
|
存储 关系型数据库 MySQL
Mysql(4)—数据库索引
数据库索引是用于提高数据检索效率的数据结构,类似于书籍中的索引。它允许用户快速找到数据,而无需扫描整个表。MySQL中的索引可以显著提升查询速度,使数据库操作更加高效。索引的发展经历了从无索引、简单索引到B-树、哈希索引、位图索引、全文索引等多个阶段。
50 3
Mysql(4)—数据库索引
|
1天前
|
关系型数据库 MySQL Linux
在 CentOS 7 中通过编译源码方式安装 MySQL 数据库的详细步骤,包括准备工作、下载源码、编译安装、配置 MySQL 服务、登录设置等。
本文介绍了在 CentOS 7 中通过编译源码方式安装 MySQL 数据库的详细步骤,包括准备工作、下载源码、编译安装、配置 MySQL 服务、登录设置等。同时,文章还对比了编译源码安装与使用 RPM 包安装的优缺点,帮助读者根据需求选择最合适的方法。通过具体案例,展示了编译源码安装的灵活性和定制性。
14 2

推荐镜像

更多