情景说明:工作上遇到一个树形结构的数据,如有文件夹和子文件夹这样的数据。由于后端逻辑问题,导致在前端页面操作了删除功能后,数据库中仅部分数据被删除,比如只把根节点或是父节点删除了,没有级联删除所有子节点。然后实施那边的同事要求把数据再恢复回来,我找到运维的同事帮忙把前一天备份的数据给提取出来了,是一大堆
insert into
的语句,按理说我只要把被删掉的那几条数据插进去即可。
问题主要就是如何找出这几条数据来,有这么两种思路:
1.先把这一堆insert语句插到另一个表中,然后与业务表关联查询,找出被删除的列,然后单独复制出insert这几行数据的语句
2.修改这一堆insert语句,详见mysql insert if exists_mysql数据库中的insert if not exists
上面提到的两种方法都是可以的,只是稍微有一点点费力,我找到了如下的方式
ON DUPLICATE KEY UPDATE
insert into users values(1,"张三","123") ON DUPLICATE KEY UPDATE id = id;
ON
之前的内容为运维给过来的插入语句,其后的内容为新加上来的。意思是如果该行数据插入时报DUPLICATE
的错的话,就把该行ID的值更新为原来ID的值,也就是不更新,执行后也可以看到影响行数是0。这样相当于啥也没做,但是不报错了,也就实现了我的需求,已存在的插入语句啥也不做,也不报错。
这种方式的话,只需要在运维给过来的每一行INSERT
语句的末尾添加上ON DUPLICATE KEY UPDATE id = id
即可。如下,只需要正则替换一下就可以了
IGNORE
INSERT IGNORE INTO t (i) VALUES(1),(1)
这个ignore
会忽略所有ignorable的错误,然后产生warnings信息
mysql> SET sql_mode = '';
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO t (i) VALUES('abc');
Query OK, 1 row affected, 1 warning (0.01 sec)
mysql> SHOW WARNINGS;
+---------+------+--------------------------------------------------------+
| Level | Code | Message |
+---------+------+--------------------------------------------------------+
| Warning | 1366 | Incorrect integer value: 'abc' for column 'i' at row 1 |
+---------+------+--------------------------------------------------------+
1 row in set (0.00 sec)
应该也是可以实现这种需求的。
参考官方文档:
页面最下端:https://dev.mysql.com/doc/refman/5.7/en/insert.html
有使用示例的:https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#ignore-effect-on-execution