【Mysql】 sql语句实现update_or_create(唯一索引 ON DUPLICATE KEY UPDATE)

文章介绍了MySQL的ONDUPLICATEKEYUPDATE语句,用于在数据导入时实现数据的插入或更新。该特性简化了开发,提高了效率,特别是在批量操作中。然而,它不是SQL标准语法,可能造成迁移问题,并且在复杂或大数据量环境下可能引发问题。文章提供了一个存储股票每日数据的案例,展示了如何利用此特性处理联合唯一索引的表。

【Mysql】 on duplicate key update用法、优缺点以及使用案例

1. 应用场景:

   导入数据功能,需要实现数据不存在时进行新建,有数据修改时则进行更新。
   在实现时,思路通常为先判断数据是新增还是更新,除了我们在代码层面实现,Mysql本身提供了
ON DUPLICATE KEY UPDATE 一步实现(Mysql独有语法)

2. ON DUPLICATE KEY UPDATE 简介:

	在MySQL数据库中,如果在insert语句后面带上ON DUPLICATE KEY UPDATE 子句,而要插入的行与
表中现有记录的惟一索引或主键中产生重复值,那么就会发生旧行的更新;如果插入的行数据与现有表
中记录的唯一索引或者主键不重复,则执行新记录插入操作。
	简而言之:**数据存在则更新,无则创建**

ON DUPLICATE KEY UPDATE sql 模板

INSERT INTO 表名 
	(字段名1, 字段名2 ) 
VALUES 
	(字段值1, 字段值2) 
ON DUPLICATE KEY UPDATE 
	字段名1 = VALUES(字段名1), 
	字段名2 = VALUES(字段名2)

3.ON DUPLICATE KEY UPDATE 优缺点

优点:
	a. 开发简单,对已有表批量插入新数据时尤其方便;
	b. 可以减少网络连接开销(减少了数据查询、操作次数),在一定量的数据操作时,效率上也提高。
缺点:
	a. MySQL私有语法,非SQL92标准语法,当迁移数据时会造成麻烦,需要改写代码。例如MySQL迁移PgSQL;
	b. 当环境复杂时,数据量大的情况下,会出现意想不到的问题。(数据量大、产生并发,建议还是用原子操作);
	c. 业务逻辑分散在应用逻辑层和数据层,会对项目维护留下隐患。

4.案例(存储股票每日数据):

a.创建 以 `symbol`和`date`组成的联合唯一索引 的表  `financial_stocks_data`
CREATE TABLE `financial_stocks_data` (
  `id` int NOT NULL AUTO_INCREMENT,
  `symbol` varchar(255) DEFAULT NULL,
  `date` varchar(255) DEFAULT NULL,
  `open_price` varchar(255) DEFAULT NULL,
  `close_price` varchar(255) DEFAULT NULL,
  `volume` varchar(255) DEFAULT NULL,
  `modify_time` datetime(6) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `financial_stocks_data_symbol_date_7ee4c125_uniq` (`symbol`,`date`),
  KEY `financial_stocks_data_modify_time_a40a61a2` (`modify_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
b.通过唯一索引,使用 ON DUPLICATE KEY UPDATE 实现 批量更新或创建sql语句
# financial_stocks_data 将插入或更新这两条数据
INSERT INTO financial_stocks_data 
	(symbol, date, open_price, close_price, volume , modify_time)
VALUES 
	('IBM', '2023-03-23', '123.81', '123.37', '4643905', '2023-03-24 10:23:35.864084'),  -- 需要插入的数据
	('IBM', '2023-03-22', '127.0', '124.05', '3549024', '2023-03-24 10:23:35.864084')
ON DUPLICATE KEY UPDATE 
	id = LAST_INSERT_ID(id),  -- 自增ID
	symbol = VALUES(symbol),
	date = VALUES(date), 
	open_price = VALUES(open_price), 
	close_price = VALUES(close_price), 
	volume = VALUES(volume), 
	modify_time = VALUES(modify_time);

PS 执行sql成功截图

在这里插入图片描述

MySQL 中,`INSERT ... ON DUPLICATE KEY UPDATE` 是一种非常实用的语句,用于处理插入数据时主键或唯一约束冲突的情况。当尝试插入一条记录时,如果发现主键或唯一索引列中的值与表中已有的记录冲突,则可以选择更新已有记录的部分字段而不是插入新记录。 ### 示例 假设有一个名为 `users` 的表,其结构如下: ```sql CREATE TABLE users ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) UNIQUE, email VARCHAR(100), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); ``` 在这个例子中,`id` 是主键,而 `username` 被定义为唯一键(UNIQUE),这意味着不能有两个用户拥有相同的用户名。 #### 插入新用户并处理重复键冲突 以下是一个使用 `INSERT ... ON DUPLICATE KEY UPDATE` 的示例: ```sql INSERT INTO users (username, email) VALUES ('john_doe', 'john@example.com') ON DUPLICATE KEY UPDATE email = 'john_newemail@example.com'; ``` 这段 SQL 代码的作用是: - 如果 `username` `'john_doe'` 还不存在于 `users` 表中,则插入一条新的记录。 - 如果 `username` `'john_doe'` 已经存在(即触发了唯一键冲突),则执行 `ON DUPLICATE KEY UPDATE` 子句,将现有记录的 `email` 字段更新为 `'john_newemail@example.com'` [^3]。 #### 结合 MyBatis 使用示例 在 MyBatis 框架中,可以很方便地使用 `INSERT ... ON DUPLICATE KEY UPDATE` 语法来实现类似功能。以下是一个 XML 映射文件中的示例片段: ```xml <insert id="insertOrUpdateUser"> INSERT INTO users (username, email) VALUES (#{user.username}, #{user.email}) ON DUPLICATE KEY UPDATE email = VALUES(email) </insert> ``` 在这个例子中,`#{user.username}` 和 `#{user.email}` 是从传入的参数对象中获取的值。当发生唯一键冲突时,会自动调用 `ON DUPLICATE KEY UPDATE` 部分,并更新 `email` 字段的值为当前插入的值 [^1]。 需要注意的是,在某些版本的 MySQL(如 8.0.20 及更高版本)中,如果在 `ON DUPLICATE KEY UPDATE` 子句中使用 `VALUES()` 函数来引用插入的值,可能会收到警告信息。这是因为 `VALUES()` 函数的行为在 `INSERT ... SELECT` 语句中可能不如预期那样工作 [^4]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yqyn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值