mysql之主键插入冲突就跟新(mybatis篇)

本文介绍如何使用MySQL的ON DUPLICATE KEY UPDATE特性解决主键冲突问题,并提供了mybatis环境下单条记录与批量导入数据的具体SQL示例。

很多时候我们都会遇到插入数据导致主键冲突这种情况,我们就希望能更新这条记录而不会报错。在MySQL1.4以后就出现相对应的关键字来解决这个问题  on duplicate key update.

 当我们在插入数据库数据的时候,遇到唯一索引或者主键冲突就会根据主键进行更新指定的字段的数据,我们一般都是基于mybatis做数据库的操作,所以我们看下mybatis是如何写sql语句的:

对于单条的数据的插入更新:

insert into rights_customer_schedule (id, cid, audit_time, 
      activity_id, 
      uid, qualified_num,application_no)
    	values (#{id,jdbcType=INTEGER}, #{cid,jdbcType=VARCHAR}, #{auditTime,jdbcType=TIMESTAMP}, 
      #{activityId,jdbcType=VARCHAR}, 
      #{uid,jdbcType=VARCHAR}, #{qualifiedNum,jdbcType=INTEGER},#{applicationNo,jdbcType=VARCHAR})
      ON DUPLICATE KEY UPDATE qualified_num = #{qualifiedNum,jdbcType=INTEGER} 
      ,datachange_lasttime = NOW()

在测试的数据中cid和activity_id建立了联合唯一索引,如果数据库存在就会更新qualified_num和datachange_lasttime

这种是单条插入时候的写法,在看下批量导入的时候:

insert into rights_customer_schedule (id, cid, audit_time, 
      activity_id,
      uid, qualified_num,application_no)
		VALUES
		<foreach collection="list" item="item" index="index"
			separator=",">
			(
			#{item.id, jdbcType=INTEGER},
			#{item.cid, jdbcType=VARCHAR},
			#{item.auditTime,jdbcType=TIMESTAMP},
			#{item.activityId,jdbcType=VARCHAR},
			#{item.uid, jdbcType=VARCHAR},
			#{item.qualifiedNum, jdbcType=INTEGER},
			#{item.applicationNo, jdbcType=INTEGER}
			)
		</foreach>
		ON DUPLICATE KEY UPDATE
		qualified_num = VALUES(qualified_num)

和单条不同的是,批量需要用foreach进行构造,而on duplicate key update 后面的字段需要用values进行修饰参数是表的字段名称。

这里好像没有设置datachange_lasttime 字段的值,其实这个值在数据库的字段类型是:

ON UPDATE CURRENT_TIMESTAMP

所以不用设置当需要更修新数据的时候,这个字段就会更新

MyBatis 中,直接配置忽略插入操作中的主键冲突并不是 MyBatis 本身的功能,而是依赖于底层使用的数据库及其 SQL 语法支持。例如,在 MySQL 中可以使用 `INSERT IGNORE` 语句来忽略主键或唯一约束冲突的情况。如果使用的是其他数据库,可能需要采用不同的策略,如 `ON CONFLICT DO NOTHING`(PostgreSQL)等。 ### 配置方法 #### 使用 MySQL 的 `INSERT IGNORE` 在 MySQL 中,`INSERT IGNORE` 会忽略主键或唯一索引冲突的错误,并继续执行插入操作。可以在 MyBatis 的映射文件中直接编写 `INSERT IGNORE` 语句: ```xml <insert id="insertIgnoreUser"> INSERT IGNORE INTO users (id, name, email) VALUES (#{id}, #{name}, #{email}) </insert> ``` 上述语句中,如果 `id` 字段(假设为主键)发生冲突MySQL 会忽略该插入操作,而不会抛出错误[^1]。 #### 使用 `ON DUPLICATE KEY UPDATE`(MySQL) 如果希望在主键冲突时执行更新操作,而不是忽略插入,可以使用 `ON DUPLICATE KEY UPDATE` 语法: ```xml <insert id="insertOrUpdateUser"> INSERT INTO users (id, name, email) VALUES (#{id}, #{name}, #{email}) ON DUPLICATE KEY UPDATE name = #{name}, email = #{email} </insert> ``` 此语句会在主键或唯一索引冲突更新已有的记录[^1]。 #### 使用 PostgreSQL 的 `ON CONFLICT DO NOTHING` 对于 PostgreSQL 数据库,可以使用 `ON CONFLICT DO NOTHING` 来忽略主键冲突: ```xml <insert id="insertIgnoreUser"> INSERT INTO users (id, name, email) VALUES (#{id}, #{name}, #{email}) ON CONFLICT (id) DO NOTHING </insert> ``` 该语句会忽略主键 `id` 冲突的情况,不会抛出错误[^1]。 ### 事务处理 如果需要在插入操作中处理主键冲突,建议将插入操作放在事务中进行管理,以确保数据的一致性。例如: ```xml <insert id="insertIgnoreUserInTransaction"> BEGIN; INSERT IGNORE INTO users (id, name, email) VALUES (#{id}, #{name}, #{email}); COMMIT; </insert> ``` ### 使用 MyBatis 动态 SQL 如果希望根据不同的数据库类型动态生成不同的 SQL 语句,可以使用 MyBatis 的动态 SQL 功能。例如: ```xml <insert id="dynamicInsert"> <choose> <when test="dbType == 'mysql'"> INSERT IGNORE INTO users (id, name, email) VALUES (#{id}, #{name}, #{email}) </when> <when test="dbType == 'postgresql'"> INSERT INTO users (id, name, email) VALUES (#{id}, #{name}, #{email}) ON CONFLICT (id) DO NOTHING </when> <otherwise> INSERT INTO users (id, name, email) VALUES (#{id}, #{name}, #{email}) </otherwise> </choose> </insert> ``` 通过动态 SQL,可以根据不同的数据库类型生成相应的插入语句,从而实现忽略主键冲突的功能[^1]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值