实现MySQL插入数据重复时更新,数据不存在时插入,只使用一条SQL语句的需求,可以通过以下几种方法来实现:
首页先创建一张表,开始测试sql
代码解读复制代码-- 创建一张users表,并把name设置为唯一索引。
CREATE TABLE `users` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
`age` int DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `name_key` (`name`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
# 插入一条数据,做测试数据
INSERT INTO `users` (`name`, `age`) VALUES ('刘备', 50);
INSERT ... ON DUPLICATE KEY UPDATE
先执行插入,如果不存在,则插入成功;如果唯一索引已存在,则删除刚刚插入的数据,再去更新之前存在的那条记录。sql
代码解读复制代码-- 再次插入这个唯一索引存在的数据,如果存在则修改
INSERT INTO `users` (`name`, `age`)
VALUES
( '刘备', 60 ) ON DUPLICATE KEY UPDATE `name` = '张飞', `age` = 30;
你会发现影响了两条数据(删除了SQL执行时新增的数据,并把原来的数据修改了)
REPLACE INTO
以唯一键判断数据是否存在。如果不存在,那么新增;如果存在,先删除原来的数据,再新增。sql
代码解读复制代码REPLACE INTO `users` (`name`, `age`)
VALUES ('张飞', '55');
你会发现影响了两条数据(删除了原来的数据,并插入了新数据)
ON DUPLICATE KEY UPDATE
高效。INSERT IGNORE
会先执行插入,如果数据不存在,则插入成功;如果存在,则不插入。由于使用了ignore,所以会忽略索引存在错误。sql
代码解读复制代码INSERT IGNORE INTO `users` (`name`, `age`)
VALUES ('张飞', 50);
你会发现没有修改任何数据(因为当前唯一索引的数据已存在)
INSERT IF NOT EXISTS
执行insert前,会先判断条件是否满足。通过not exists判断,如果不存在,则插入;如果存在,则不插入。
注意:新增记录时,select 字段 from,表名称是dual,并不是当前表。如果是当前表,那么在新增记录时(表中没有该记录)会报错。因为第2行的select从当前表查询,已经有了该值。所以必须是dual,或者是其他表也可以。sql
代码解读复制代码INSERT INTO `users` ( `name`, `age` )
SELECT
'张飞',
50
FROM
DUAL
WHERE
NOT EXISTS ( SELECT * FROM `users` WHERE `name` = '张飞' );
你会发现没有修改任何数据
NOT EXISTS
过滤掉已存在的数据,保证数据的唯一性。不需要依赖唯一索引和主键NOT EXISTS
的子查询可能性能较差,尤其是在没有索引的情况下。最后:附上所有测试SQL语句sql
代码解读复制代码CREATE TABLE `users` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL,
`age` int DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `name_key` (`name`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
INSERT INTO `users` (`name`, `age`) VALUES ('刘备', 50);
INSERT INTO `users` (`name`, `age`)
VALUES
( '刘备', 60 ) ON DUPLICATE KEY UPDATE `name` = '张飞', `age` = 30;
SHOW TABLE STATUS LIKE 'users';
REPLACE INTO `users` (`name`, `age`)
VALUES ('张飞', 55);
INSERT IGNORE INTO `users` (`name`, `age`)
VALUES ('张飞', 50);
INSERT INTO `users` ( `name`, `age` ) SELECT
'张飞',
50
FROM
DUAL
WHERE
NOT EXISTS ( SELECT * FROM `users` WHERE `name` = '张飞' );
INSERT ... ON DUPLICATE KEY UPDATE
REPLACE INTO
INSERT IGNORE
INSERT IF NOT EXISTS