需求:如果表中存在某行,那么更新即可;不存在某行,那么就新增一条。通常是将主键索引或唯一索引作为判断条件。
思路:可以使用Mysql的INSERT ... ON DUPLICATE KEY UPDATE或REPLACE或UPDATE实现。如果希望一条语句实现,可以考虑前两种实现
创建一张表,表中包含自增Id和唯一索引email。
CREATE TABLE `user_info` (
`Id` smallint(6) NOT NULL AUTO_INCREMENT,
`email` varchar(10) NOT NULL DEFAULT '' COMMENT '邮箱',
`name` varchar(10) DEFAULT '' COMMENT '用户名',
`phone` varchar(20) DEFAULT NULL COMMENT '手机号',
`desc` text COMMENT '备注',
PRIMARY KEY (`Id`),
UNIQUE KEY `email` (`email`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8 COMMENT='用户信息表';
实现一:INSERT ... ON DUPLICATE KEY UPDATE
使用前提:需要有主键索引或唯一索引。
参考资料:https://dev.mysql.com/doc/refman/5.7/en/insert-on-duplicate.html(可以先查询自己使用的Mysql版本,将链接中的5.7改为自己的版本)
1)INSERT INTO user_info (`email`,`name`,`phone`) VALUES ('333','abcd','18292') ON DUPLICATE KEY UPDATE `name` = VALUES(`name`),`phone` = VALUES(`phone`);
说明:此句中会根据唯一索引email判断user_info表中是否存在,不存在的话表中就会新加一条记录;存在的话就执行UPDATE后面的语句name=abcd,phone=18292。注意了,假如表中已经存在该email,执行一次该语句,主键Id就会加1,好像就是先给表中新增一条,然后和有冲突的行进行合并,然后将新增的记录删除。可以根据图中操作直观感受,注意主键Id是不连续的。至于该语句执行后返回结果有0,1,2,可参考官网得到答案:With ON DUPLICATE KEY UPDATE, the affected-rows value per row is 1 if the row is inserted as a new row, 2 if an existing row is updated, and 0 if an existing row is set to its current values.
2)INSERT INTO user_info (`Id`,`desc`) VALUES ('5','hello world') ON DUPLICATE KEY UPDATE `desc` = VALUES(`desc`);
说明:此句会根据主键Id判断user_info表中是否存在,不存在的话表中就会新加一条记录;存在的话就执行UPDATE后面的语句desc=hello world。注意了,这里与1)有所不同,不管表中是否存在该Id对应记录,自增Id都不会加1。
3)如有需求在一句中有多个唯一索引等进行更新或新增,可详见官网说明,不过一般需避免这种情况:In general, you should try to avoid using an ON DUPLICATE KEY UPDATE
clause on tables with multiple unique indexes。
实现二:REPLACE
为了避免写入重复数据,建议使用REPLACE时最好考虑唯一索引或主键索引的存在。
参考地址:https://dev.mysql.com/doc/refman/5.7/en/replace.html
1)REPLACE INTO user_info(`email`,`name`,`phone`) VALUES ('77777', 'yaya','2222');
可对比实现一,REPLACE的工作方式与INSERT完全相同,不同之处在于,如果表中的旧行与UNIQUE KEY的新行具有相同的值,则在插入新行之前会删除该旧行。体会一下与实现一的1)的区别:该方式也会造成主键Id变化,不过是插入新行之前先删除旧行。
2)REPLACE INTO user_info(`Id`,`desc`) VALUES (9, 'welcome');
说明:此句会根据主键Id判断user_info表中是否存在,不存在的话表中就会新加一条记录;存在的话就执行UPDATE后面的语句desc=welcome。注意了,这里与1)有所不同,不管表中是否存在该Id对应记录,自增Id都不会加1。
实现三:UPDATE
上面两种实现都极有可能存在自增Id不连续的情况。
参考地址:https://dev.mysql.com/doc/refman/5.7/en/update.html
可以先使用UPDATE更新,不存在的话会返回影响行数0,可以判断是不存在该记录的,可以继续INSERT INTO;存在的话会更新同时返回影响行数。