sql 如果不存在则插入,存在则不操作或修改

本文深入探讨了五种SQL插入策略:使用虚表dual与notEXISTS防止重复插入,replaceinto实现高效数据替换,ONDUPLICATEKEYUPDATE确保数据一致性,从其他表批量导入数据,以及利用唯一索引控制重复。每种方法都附有实例,适用于不同场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原文链接:https://blog.youkuaiyun.com/weixin_40533111/article/details/84137404 作者四月天五月雨^_^,转载请注明出处,谢谢

前言

本文介绍几种数据库SQL插入问题,如果存在该记录,则不操作或者执行更新,每种方式都有各自适应的场景,一一举例

目录:

1.虚表dual 加条件 not EXISTS
2.使用replace into
3.使用ON DUPLICATE KEY UPDATE
4.从其他表获取数据
5.设置唯一索引

正文:

1.虚表dual 加条件 not EXISTS

表现状:一张新建标签表tag,主键id自增,另外几个普通字段
在这里插入图片描述
现在有个 需求: 新插入一个标签, 要求item_key,item_value不能同时重复,否则不插入
选择: 首先排除4,接着排除3,5,因为普通列上没有设置索引,(可以设置唯一索引在两个列上,这样插入重复时,会索引重复导致失败,会抛出异常,如果频繁插入重复,损耗性能,不建议); 现有的标签在其他表中可能存在引用,故不能使用2的replace,综合考虑使用方式1

步骤:
使用虚表dual后跟条件 EXISTS,
eg:
insert into tag (category,item_key,item_value) select 'test1','key1','value1' from dual where NOT EXISTS (SELECT id FROM tag WHERE category='test1' and item_key='key1' and item_value='value1')
在这里插入图片描述

2.使用replace into

场景:如果确定存量的数据不重要,那么可以使用replace,简单高效,类似insert into的升级版,但操作的列必须存在唯一索引(主键包含唯一索引),
1 在三个列上加上unique索引(根据实际列数)
在这里插入图片描述
2.使用replace

replace  into tag (category,item_key,item_value)
values( 'test1','key1','value1' );

可以看到,id为1的那条记录被删除,之后又插入一条新纪录,id为1240;
在这里插入图片描述

3.使用ON DUPLICATE KEY UPDATE

需求:如果不存在则插入,存在则更新value键,进行加1(举例用的字符串,实际生产中可能是int),
DUPLICATE 命令需作用在有唯一索引的的列上,如果这列索引有重复则执行update,否则执行insert.

INSERT INTO tag (category,item_key,item_value) VALUES ('test1','key1','value1') ON DUPLICATE KEY UPDATE item_value='value_3';

在这里插入图片描述

4.从其他表获取数据

这点和题目不符了,算是个批处理

INSERT INTO tag (category,item_key,item_value) 
SELECT category,item_key,item_value from tag_copy where id in(SELECT id from tag_copy where item_value like 'value%');

5.设置唯一索引

步骤可参考第三条,此处做点补充,因为是使用索引来控制插入不重复,那么有个问题,当索引重复时程序会异常,需要cache异常,而在批处理中,如果再使用这种高频度,性能不高的,应通过其他方式控制.
在这里插入图片描述



春水碧于天,画船听雨眠。

<think>我们在SQL和XML环境下操作,通常是在MyBatis框架中编写映射文件(XML)来实现。 需求:根据主键判断数据是否存在,循环插入更新数据到表中(即批量操作存在则更新,存在插入) 在MySQL中,我们可以使用ON DUPLICATE KEY UPDATE语法来实现单条数据的“存在更新,存在插入”。对于批量操作,同样可以使用此语法,但需要将多条数据用VALUES()函数分别指定更新值。 步骤: 1. 在Mapper接口中定义方法,参数为List(要操作的数据列表) 2. 在XML映射文件中,使用<insert>标签,并编写SQL语句 3. SQL语句使用INSERT INTO ... VALUES ... ON DUPLICATE KEY UPDATE ... 的格式 4. 对于批量操作,使用MyBatis的<foreach>标签遍历列表,生成多条VALUES记录 注意:该操作依赖于主键唯一索引。当插入的数据导致主键唯一索引冲突时,就会执行更新操作。 假设我们有一个表`product`,主键为`id`(者有唯一索引的字段,比如`code`),我们以`code`作为判断依据(唯一索引)。 示例XML配置(参考引用[3]并修改为批量操作): 注意:在批量操作中,ON DUPLICATE KEY UPDATE后面跟的更新字段,如果要使用插入时的值,可以使用VALUES(字段名)来获取(这样即使批量插入,每个记录更新时也会使用对应插入记录的值)。 具体实现如下:</think>### 在 SQL 和 MyBatis XML 中实现循环插入/更新操作 根据主键判断数据是否存在并执行插入更新操作,在 MySQL 中可通过 `ON DUPLICATE KEY UPDATE` 语法实现。以下是具体实现方案: #### 1. SQL 核心语法 ```sql INSERT INTO 表名 (字段1, 字段2, 主键字段) VALUES (值1, 值2, 主键值), (值1, 值2, 主键值) ON DUPLICATE KEY UPDATE 字段1 = VALUES(字段1), 字段2 = VALUES(字段2); ``` - **执行逻辑**:当主键冲突时自动转为更新操作 - **VALUES() 函数**:动态引用 INSERT 语句中的值 - **必要条件**:必须存在主键唯一索引约束[^1][^3] #### 2. MyBatis XML 实现 ```xml <insert id="insertOrUpdateBatch"> INSERT INTO your_table (id, name, status, update_time) VALUES <foreach item="item" collection="list" separator=","> ( #{item.id}, #{item.name}, #{item.status}, NOW() ) </foreach> ON DUPLICATE KEY UPDATE name = VALUES(name), status = VALUES(status), update_time = NOW() </insert> ``` #### 3. 关键配置说明 | 组件 | 作用 | |----------------|----------------------------------------------------------------------| | `<foreach>` | 遍历 List 参数生成批量 VALUES 子句 | | `VALUES(字段)` | 引用 INSERT 时传入的值,避免硬编码更新值 | | `NOW()` | 自动设置更新时间戳 | | 主键约束 | 表中必须存在 PRIMARY KEY UNIQUE 索引 | #### 4. 性能优化建议 1. **批量分段**:单次处理 500-1000 条数据,避免超大 SQL ```java // Java 中分批处理示例 List<List<Item>> batches = Lists.partition(fullList, 500); batches.forEach(batch -> mapper.insertOrUpdateBatch(batch)); ``` 2. **索引优化**:确保判断字段有索引 3. **事务控制**:在 Service 层添加 `@Transactional` 注解 #### 5. 使用场景示例 ```java // 实体类 public class Product { private Long id; // 主键 private String name; private Integer status; } // Mapper 接口 void insertOrUpdateBatch(List<Product> products); ``` > **注意**:SQL Server 可使用 `MERGE INTO` 语法,Oracle 用 `MERGE` 语句实现相同功能,语法结构有所同[^1]。 --- ### 相关问题 1. 如何优化 MyBatis 批量操作的性能? 2. `ON DUPLICATE KEY UPDATE` 和 `REPLACE INTO` 有什么区别? 3. 在多数据库兼容的场景下如何实现存在则更新? 4. 批量操作时如何避免死锁问题? 5. 如何通过 MyBatis 注解方式实现存在更新逻辑? [^1]: MySQL 官方文档:ON DUPLICATE KEY UPDATE 语法 [^2]: MyBatis 批量操作最佳实践 [^3]: 数据库唯一约束与索引设计原则
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值