MySQL replace into 语句浅析(一)

   这篇文章主要介绍了MySQL replace into 语句浅析(一),本文讲解了replace into的原理、使用方法及使用的场景和使用示例,需要的朋友可以参考下

  一 介绍

  在笔者支持业务过程中,经常遇到开发咨询replace into 的使用场景以及注意事项,这里做个总结。从功能原理,性能和注意事项上做个说明。

  二 原理

  2.1 当表中存在主键但是不存在唯一建的时候。

  表结构

  代码如下:

  CREATE TABLE `yy` (

  `id` bigint(20) NOT NULL,

  `name` varchar(20) DEFAULT NULL,

  PRIMARY KEY (`id`)

  ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

  root@test 02:43:58>insert into yy values(1,'abc');

  Query OK, 1 row affected (0.00 sec)

  root@test 02:44:25>replace into yy values(2,'bbb');

  Query OK, 1 row affected (0.00 sec)

  root@test 02:55:42>select * from yy;

  +----+------+

  | id | name |

  +----+------+

  | 1 | abc |

  | 2 | bbb |

  +----+------+

  2 rows in set (0.00 sec)

  root@test 02:55:56>replace into yy values(1,'ccc');

  Query OK, 2 rows affected (0.00 sec)

  如果本来已经存在的主键值,那么MySQL做update操作。

   代码如下:

  ### UPDATE test.yy

  ### WHERE

  ### @1=1 /* LONGINT meta=0 nullable=0 is_null=0 */

  ### @2='abc' /* VARSTRING(60) meta=60 nullable=1 is_null=0 */

  ### SET

  ### @1=1 /* LONGINT meta=0 nullable=0 is_null=0 */

  ### @2='ccc' /* VARSTRING(60) meta=60 nullable=1 is_null=0 */

  如果本来相应的主键值没有,那么做insert 操作 replace into yy values(2,'bbb');

   代码如下:

  ### INSERT INTO test.yy

  ### SET

  ### @1=2 /* LONGINT meta=0 nullable=0 is_null=0 */

  ### @2='bbb' /* VARSTRING(60) meta=60 nullable=1 is_null=0 */

  # at 623

  #140314 2:55:42 server id 136403306 end_log_pos 650 Xid = 6090885569

  2.2 当表中主键和唯一键同时存在时

   代码如下:

  CREATE TABLE `yy` (

  `id` int(11) NOT NULL DEFAULT '0',

  `b` int(11) DEFAULT NULL,

  `c` int(11) DEFAULT NULL

  PRIMARY KEY (`a`),

  UNIQUE KEY `uk_bc` (`b`,`c`)

  ) ENGINE=InnoDB DEFAULT CHARSET=utf8

  情形1 主键冲突

  代码如下:

  root@test 04:37:18>replace into yy values(1,2,3);

  Query OK, 1 row affected (0.00 sec)

  root@test 04:37:37>replace into yy values(2,2,4);

  Query OK, 1 row affected (0.00 sec)

  root@test 04:38:05>select * from yy;

  +----+------+------+

  | id | b | c |

  +----+------+------+

  | 1 | 2 | 3 |

  | 2 | 2 | 4 |

  +----+------+------+

  2 rows in set (0.00 sec)

  root@test 04:38:50>replace into yy values(1,2,5);

  Query OK, 2 rows affected (0.00 sec)

  root@test 04:38:58>select * from yy;

  +----+------+------+

  | id | b | c |

  +----+------+------+

  | 2 | 2 | 4 |

  | 1 | 2 | 5 |

  +----+------+------+

  2 rows in set (0.00 sec)

  主键冲突时,数据库对表做先删除然后插入的操作,也即先删除id=1的记录,然后插入新的id=1 的记录(1,2,5).

   代码如下:

  BINLOG '

  Io5hVROWYHC+KwAAAEICAAAAAMoMAAAAAAEABHRlc3QAAnl5AAMDAwMABg==

  Io5hVRmWYHC+KgAAAGwCAAAAAMoMAAAAAAAAA//4AQAAAAIAAAADAAAA

  ### DELETE FROM test.yy

  ### WHERE

  ### @1=1 /* INT meta=0 nullable=0 is_null=0 */

  ### @2=2 /* INT meta=0 nullable=1 is_null=0 */

  ### @3=3 /* INT meta=0 nullable=1 is_null=0 */

  Io5hVReWYHC+KgAAAJYCAAAAAMoMAAAAAAEAA//4AQAAAAIAAAAFAAAA

  '/*!*/;

  ### INSERT INTO test.yy

  ### SET

  ### @1=1 /* INT meta=0 nullable=0 is_null=0 */

  ### @2=2 /* INT meta=0 nullable=1 is_null=0 */

  ### @3=5 /* INT meta=0 nullable=1 is_null=0 */

  # at 662

  #150524 16:38:58 server id 3195035798 end_log_pos 689 Xid = 22962508

  COMMIT/*!*/

  情形2 唯一建冲突

  代码如下:

  root@test 04:48:30>select * from yy;

  +----+------+------+

  | id | b | c |

  +----+------+------+

  | 1 | 2 | 4 |

  | 2 | 2 | 5 |

  | 3 | 3 | 5 |

  | 4 | 3 | 6 |

  +----+------+------+

  4 rows in set (0.00 sec)

  root@test 04:53:21>replace into yy values(5,3,6);

  Query OK, 2 rows affected (0.00 sec)

  root@test 04:53:40>select * from yy;

  +----+------+------+

  | id | b | c |

  +----+------+------+

  | 1 | 2 | 4 |

  | 2 | 2 | 5 |

  | 3 | 3 | 5 |

  | 5 | 3 | 6 |

  +----+------+------+

  4 rows in set (0.00 sec)

  主键不冲突,唯一键冲突时,数据库对表 唯一键为(3,6)的行做update操作,将主键修改为要插入的值,id=4 改为id=5。

   代码如下:

  BINLOG '

  lJFhVROWYHC+KwAAANoAAAAAAMoMAAAAAAEABHRlc3QAAnl5AAMDAwMABg==

  lJFhVRiWYHC+OAAAABIBAAAAAMoMAAAAAAEAA///+AQAAAADAAAABgAAAPgFAAAAAwAAAAYAAAA=

  '/*!*/;

  ### UPDATE test.yy

  ### WHERE

  ### @1=4 /* INT meta=0 nullable=0 is_null=0 */

  ### @2=3 /* INT meta=0 nullable=1 is_null=0 */

  ### @3=6 /* INT meta=0 nullable=1 is_null=0 */

  ### SET

  ### @1=5 /* INT meta=0 nullable=0 is_null=0 */

  ### @2=3 /* INT meta=0 nullable=1 is_null=0 */

  ### @3=6 /* INT meta=0 nullable=1 is_null=0 */

  # at 274

  #150524 16:53:40 server id 3195035798 end_log_pos 301 Xid = 22962872

  COMMIT/*!*/

  情形3 主键和唯一键同时冲突,如果需要插入的值的主键 和唯一和表中已经存在的存在冲突。

   代码如下:

  root@test 04:53:52>replace into yy values(1,3,6);

  Query OK, 3 rows affected (0.00 sec) ---注意此处影响的行数是3

  root@test 04:55:35>select * from yy;

  +----+------+------+

  | id | b | c |

  +----+------+------+

  | 2 | 2 | 5 |

  | 3 | 3 | 5 |

  | 1 | 3 | 6 |

  +----+------+------+

  3 rows in set (0.00 sec)

  要插入的值(1,3,6) 主键于 表里面的id=1的值冲突,唯一键(3,6)和表中id=5的记录冲突,MySQL 处理的时候 ,先删除id=1的行,然后更新了id=5的行。

   代码如下:

  BINLOG '

  B5JhVROWYHC+KwAAAJwBAAAAAMoMAAAAAAEABHRlc3QAAnl5AAMDAwMABg==

  B5JhVRmWYHC+KgAAAMYBAAAAAMoMAAAAAAAAA//4AQAAAAIAAAAEAAAA

  ### DELETE FROM test.yy

  ### WHERE

  ### @1=1 /* INT meta=0 nullable=0 is_null=0 */

  ### @2=2 /* INT meta=0 nullable=1 is_null=0 */

  ### @3=4 /* INT meta=0 nullable=1 is_null=0 */

  B5JhVRiWYHC+OAAAAP4BAAAAAMoMAAAAAAEAA///+AUAAAADAAAABgAAAPgBAAAAAwAAAAYAAAA=

  '/*!*/;

  ### UPDATE test.yy

  ### WHERE

  ### @1=5 /* INT meta=0 nullable=0 is_null=0 */

  ### @2=3 /* INT meta=0 nullable=1 is_null=0 */

  ### @3=6 /* INT meta=0 nullable=1 is_null=0 */

  ### SET

  ### @1=1 /* INT meta=0 nullable=0 is_null=0 */

  ### @2=3 /* INT meta=0 nullable=1 is_null=0 */

  ### @3=6 /* INT meta=0 nullable=1 is_null=0 */

  # at 510

  #150524 16:55:35 server id 3195035798 end_log_pos 537 Xid = 22962904

  COMMIT/*!*/

  三 结论

  对表进行replace into操作的时候,

  当不存在冲突时,replace into 相当于insert操作。

  当存在pk冲突的时候是先delete再insert,如果主键是自增的,则自增主键会做 +1 操作。【5.5,5.6版本均做过测试】

  当存在uk冲突的时候是直接update。,如果主键是自增的,则自增主键会做 +1 操作。 【5.5,5.6版本均做过测试】


  了解上述原理和结论之后,以后再遇到replace into 的时候,相信各位读者可以知道如何选择,由于篇幅限制,后续文章会基于replace into原理,讲述生产过程中的注意事项。

时间: 2024-10-28 04:27:11

MySQL replace into 语句浅析(一)的相关文章

MySQL replace into 语句浅析(二)

  这篇文章主要介绍了MySQL replace into 语句浅析(二),本文着重给出了几个特殊案例分析,需要的朋友可以参考下 一 介绍 上一篇文章介绍了replace into的基本原理.本章内容通过一个例子说明 replace into 带来的潜在的数据质量风险,当涉及replace into操作的表含有自增主键时,主备切换后会造成数据覆盖等不一致的情况发生. 二 案例分析 在主库上操作 代码如下: root@test 12:36:51>show create table t1 G ***

MySQL replace into 语句浅析(二)_Mysql

一 介绍   上一篇文章介绍了replace into的基本原理.本章内容通过一个例子说明 replace into 带来的潜在的数据质量风险,当涉及replace into操作的表含有自增主键时,主备切换后会造成数据覆盖等不一致的情况发生. 二 案例分析 在主库上操作 复制代码 代码如下: root@test 12:36:51>show create table t1 \G *************************** 1. row *************************

MySQL Replace INTO语句的用法

天DST里面有个插件作者问我关于Replace INTO和INSERT INTO的区别,我和他说晚上上我的blog看吧,那时候还在忙,现在从MYSQL手册里找了点东西,MYSQL手册里说REPLACE INTO说的还是比较详细的. REPLACE的运行与INSERT很相像.只有一点除外,如果表中的一个旧记录与一个用于PRIMARY KEY或一个UNIQUE索引的新记录具有相同的值,则在新记录被插入之前,旧记录被删除.请参见13.2.4节,"INSERT语法". 注意,除非表有一个PRI

mysql replace into语句学习

实践过程:id 是主键测试方式一,插入索引值是一样的:REPLACE INTO  fanwe_order(id,sn)  VALUES('33','测试replace into 使用')  结果:受影响的行数: 2 SELECT * FROM fanwe_order WHERE sn='测试replace into 使用'  结果:查出 一行记录 测试方式二,插入主键值是重复的: 将插入id指定为34.这样不与数据表中的id有重复现象,之后运行查询 REPLACE INTO  fanwe_ord

MySQL replace函数替换字符串语句的用法_Mysql

MySQL replace函数我们经常用到,下面就为您详细介绍MySQL replace函数的用法,希望对您学习MySQL replace函数方面能有所启迪. 最近在研究CMS,在数据转换的时候需要用到mysql的MySQL replace函数,这里简单介绍一下. 比如你要将表 tb1里面的 f1字段的abc替换为def UPDATE tb1 SET f1=REPLACE(f1, 'abc', 'def'); REPLACE(str,from_str,to_str) 在字符串 str 中所有出现

mysql在SQL语句中使用replace替换字符

本来不想告诉大家的,因为采集别人网站不是什么光彩事,但觉得这个技巧实在是够强,要不是这简短的一行代码,我还不累死了.是这样的,采集了一些别人的文章,可能是采集程序的问题,每篇文章的标题里都多出了一些字符<img src="images/awwor.gif">,导致在生成HTML网页后很多内容不显示,但是看了看记录有2000多条,一条一条改,还不累死我啊.于是请教了一个SQL高手,发我一行SQL语句:  代码如下 复制代码 Update dede_addonsoft SET

MySQL Replace INTO学习

MySQL Replace INTO说明 REPLACE的运行与INSERT很相像.只有一点除外,如果表中的一个旧记录与一个用于PRIMARY KEY或一个UNIQUE索引的新记录具有相同的值,则在新记录被插入之前,旧记录被删除.请参见13.2.4节,"INSERT语法". 注意,除非表有一个PRIMARY KEY或UNIQUE索引,否则,使用一个REPLACE语句没有意义.该语句会与INSERT相同,因为没有索引被用于确定是否新行复制了其它的行. 所有列的值均取自在REPLACE语句

RDS for MySQL CPU 性能问题浅析

RDS for MySQL CPU 性能问题浅析 1. 原因 1.1 应用负载高 1.2 查询执行成本高 2. 解决方法2.1 相关工具 2.2 应用负载高 2.3 查询语句执行成本高 3. 避免出现的一般原则 RDS for MySQL 实例在日常使用中,会碰到 CPU 使用率达到 100% 的情况.比如: 1. 原因 根本原因:应用提交的查询访问的 逻辑读(逻辑 IO) 总量 (需要访问的 表 数据) 过高. 大量逻辑读会导致数据缓存 Buffer Pool 中用于维护数据一致性的 Latc

mysql replace用法

mysql replace用法 昨天因为导入 数据时一条数据出来了,后面就想到用update 与replace结合作操哦, update tablename set fields=replace('aa','bb',str) where 1.replace into replace into table (id,name) values('1','aa'),('2','bb') 此语句的作用是向表table中插入两条记录.如果主键id为1或2不存在 就相当于 insert into table