MySQL insert

Posted 丹柿小院

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL insert相关的知识,希望对你有一定的参考价值。

向数据表中插入数据时,通常存在以下逻辑:

1)判断数据是否存在;

2)如果不存在,则插入;

3)如果存在,则进行其他处理。


因此在 insert 语法基础上,出现了其他语法,如:

  • on duplicate key update

  • replace

  • insert ignore


1 insert

1.1 概念

用于向已存在的表中插入新行。

基本语法如下所示。

 
   
   
 
INSERT [INTO] tbl_name[(col_name [, col_name] ...)]{VALUES | VALUE} (value_list) [, (value_list)] ...

如果数据已存在,insert语句将报错,如 duplicate-key error。


1.2 测试

查看表结构

 
   
   
 
mysql> desc t;+-------+-------------+------+-----+---------+-------+| Field | Type | Null | Key | Default | Extra |+-------+-------------+------+-----+---------+-------+| id | int(10) | NO | PRI | NULL | || a | int(10) | YES | UNI | NULL | || name | varchar(20) | YES | | NULL | |+-------+-------------+------+-----+---------+-------+3 rows in set (0.00 sec)

查看数据

 
   
   
 
mysql> select * from t limit 3 ;+----+------+------+| id | a | name |+----+------+------+| 1 | 1 | test || 2 | 2 | test || 3 | 3 | test |+----+------+------+3 rows in set (0.00 sec)

主键冲突,实际上这条SQL存在主键冲突与唯一键冲突。

 
   
   
 
mysql> insert into t (id,a,name) values(1,2,'test1');ERROR 1062 (23000): Duplicate entry '1' for key 'PRIMARY'

以下两种语法支持插入时避免唯一键冲突导致插入失败。

  • INSERT ... ON DUPLICATE KEY UPDATE,表示 插入 或 删除和插入;

  • replace,表示 插入 或 更新。


2 on duplicate key update

2.1 概念

INSERT ... ON DUPLICATE KEY UPDATE 用于解决重复性问题。

首先判断记录是否存在,存在时更新,不存在时插入。

因此重点在于判断记录是否存在。


判断标准是如果插入的记录导致一个唯一索引或主键重复,就认为该记录已存在。


根据受影响行数可以区分该语句实际上执行的是插入还是更新。

  • 受影响行数为1,表明行作为新纪录插入;

  • 受影响行数为2,表明行重复,原有记录被更新;

  • 受影响行数为0,表明更新的数据与原数据一样,实际上未更新。


查询官方文档。

INSERT with an ON DUPLICATE KEY UPDATE clause enables existing rows to be updated if a row to be inserted would cause a duplicate value in a UNIQUE index or PRIMARY KEY.


2.2 测试

如下所示,依次执行 on duplicate key update a=values(a), name=values(name) 与 on duplicate key update a=values(a) 均执行失败,报错唯一键冲突。

执行 on duplicate key update name=values(name) 时执行成功,返回受影响行数为2。
重新查询数据表,显示主键为1的记录唯一键不变,name字段改变。

MySQL insert

将主键为1的记录修改为原始记录后重新插入完全相同的记录,返回受影响行数为0,数据不变。

MySQL insert


2.3 与 update 的区别
需要注意的是 INSERT ... ON DUPLICATE KEY UPDATE 与 update 有区别。

假设 a 列有唯一键约束,有一列值为1,以下两条语句作用相似。
INSERT INTO t1 (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE c=c+1;
UPDATE t1 SET c=c+1 WHERE a=1;
但是这里的 insert 语句与 update 语句作用不完全相同。
For an InnoDB table where a is an auto-increment column, the INSERT statement increases the auto-increment value but the UPDATE does not.


但是如果 b 字段也有唯一键约束,insert 语句等价的 update 语句变为:
 
   
   
 
UPDATE t1 SET c=c+1 WHERE a=1 OR b=2 LIMIT 1;
如果 a=1 OR b=2 条件匹配多条记录,只有一条会被更新。
因此,如果有多个唯一键,通常不会使用 INSERT ... ON DUPLICATE KEY UPDATE 语法。

2.4 timestamp
为了理解 on duplicate key update 中的 on update,举一个相关但是不同的理子,时间戳。
区分 CURRENT_TIMESTAMP 与 ON UPDATE CURRENT_TIMESTAMP:
  • CURRENT_TIMESTAMP,适用于 insert 场景,写入后不变;
  • ON UPDATE CURRENT_TIMESTAMP,适用于 update 场景,其他字段变更时自动更新。

建表,其中包括 create_time 与 update_time。
 
   
   
 
mysql> show create table t4 \G *************************** 1. row *************************** Table: t4Create Table: CREATE TABLE `t4` ( `id` int(11) DEFAULT NULL, `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间') ENGINE=InnoDB DEFAULT CHARSET=utf81 row in set (0.00 sec)
插入一行记录。
 
   
   
 
mysql> insert into t4(id) values(1);Query OK, 1 row affected (0.01 sec)mysql> mysql> select * from t4;+------+---------------------+---------------------+| id | create_time | update_time |+------+---------------------+---------------------+| 1 | 2021-07-30 14:38:23 | 2021-07-30 14:38:23 |+------+---------------------+---------------------+1 row in set (0.00 sec)
更新 id 字段,重新查看显示 create_time 不变,update_time 更新。
 
   
   
 
mysql> update t4 set id=2 where id=1;Query OK, 1 row affected (0.01 sec)Rows matched: 1 Changed: 1 Warnings: 0mysql> mysql> select * from t4;+------+---------------------+---------------------+| id | create_time | update_time |+------+---------------------+---------------------+| 2 | 2021-07-30 14:38:23 | 2021-07-30 14:38:36 |+------+---------------------+---------------------+1 row in set (0.00 sec)

备注:
各种时间与日期的数据类型对比如下图所示。

MySQL insert


3 replace
3.1 概念
replace 语句的执行过程如下所示:
1)尝试向表中插入新行
2)如果插入失败,报错主键或唯一索引导致的的重复键时:
  • 从表中删除重复的键值冲突的行;
  • 再次尝试向表中插入新行。

根据受影响行数也可以区分该语句实际上执行的是插入还是删除和插入。
  • 受影响行数为1,表明行作为新纪录插入;
  • 受影响行数大于1,表明行重复,原有记录被删除后插入;

查询官方文档。
REPLACE works exactly like INSERT, except that if an old row in the table has the same value as a new row for a PRIMARY KEY or a UNIQUE index, the old row is deleted before the new row is inserted.


3.2 测试
查询当前数据

MySQL insert

执行 insert into 报错,实际上存在两个冲突,包括主键冲突与唯一键冲突。
replace into 时显示受影响行数为3。

MySQL insert

重新查询,表明两个冲突行都先被删除,然后插入新行。

MySQL insert


4 insert ignore
4.1 概念
除了以上两种语法,insert into 也可以用于避免唯一键冲突。
insert ignore 与 replace 处理唯一键冲突的方法相反,它不会删除原纪录,而是直接跳过该记录,存在冲突的原纪录不变。

If you use the IGNORE modifier, ignorable errors that occur while executing the INSERT statement are ignored. For example, without IGNORE, a row that duplicates an existing UNIQUE index or PRIMARY KEY value in the table causes a duplicate-key error and the statement is aborted.
With IGNORE, the row is discarded and no error occurs. Ignored errors generate warnings instead.


4.2 测试
查询当前数据

MySQL insert

执行 insert into 报错,实际上存在两个冲突,包括主键冲突与唯一键冲突。
insert ignore 时显示受影响行数为0,并提示 warnings。

查询 warnings,显示主键冲突。


5 结论
要求表中存在主键或唯一索引时才有效果,否则语法失效,表中将出现重复数据。
replace 与 on duplicate key update 的主要区别包括:
  • replace 当记录不存在时insert,存在时先delete后insert。on duplicate key update 执行insert或update;
  • 对于删除和添加操作,replace 需要重复维护索引,因此大批量更新时 replace 的性能低于 on duplicate key update;
而 insert ignore 在遇到冲突时,将跳过不执行。

6 待办
  • 三种语句的常见使用场景

7 参考教程
  • ON DUPLICATE KEY UPDATE 用法与说明:https://blog.csdn.net/zyb2017/article/details/78449910
  • mysql INSERT ... ON DUPLICATE KEY UPDATE语句:https://blog.csdn.net/analogous_love/article/details/71085001
  • MySQL replace into 用法(insert into 的增强版):https://blog.csdn.net/risingsun001/article/details/38977797
  • INSERT Statement:https://dev.mysql.com/doc/refman/5.7/en/insert.html
  • REPLACE Statement:https://dev.mysql.com/doc/refman/5.7/en/replace.html
  • INSERT ... ON DUPLICATE KEY UPDATE Statement:https://dev.mysql.com/doc/refman/5.7/en/insert-on-duplicate.html
  • 最清晰易懂的Mysql CURRENT_TIMESTAMP和ON UPDATE CURRENT_TIMESTAMP区别:https://www.cnblogs.com/liangmingshen/p/11008544.html

    以上是关于MySQL insert的主要内容,如果未能解决你的问题,请参考以下文章

    c语言连接mysql——insert的代码实现

    discuz X3.1 源代码阅读,记录代码片段

    MySQL 关于表复制 insert into 语法的详细介绍

    部分代码片段

    linux中怎么查看mysql数据库版本

    php mysql_insert_id()