mysql实现不存在就插入,存在就更新,sql直接执行和mybatis实现的坑!

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: insert into ... on duplicate key update 字段=新值, mybatis执行报错: SQLException: No value specified for parameter 4,你甚至惊奇的发现你只传了3个参数却提示没找到第4个参数......亲身经历什么叫一个bug找一天

需求背景:数据表中有物理主键id,按照每次会话保存笔记,这里session_id作为每次会话的凭证,所以每次会话中可能会不断更新笔记,笔记存在就更新笔记,不存在就插入笔记

我想大家都会用

insert into 表名(字段1,字段2,...) values(值1, 值2,...) on duplicate key update 字段1=值1, 字段2=值2...

上面语法在mysql直接执行sql语句是没问题的,但是mybatis就有大坑。我个人完全不推荐这么用等号赋值,而是用values,在文章末尾会给出推荐写法。

该语句是基于唯一索引或主键使用,比如一个字段session_id被加上了unique index,并且表中已经存在了该session_id的记录值,那么插入就会更新。如果是物理主键id,那就参数需要带上这个id,不然id递增就会成为新记录

INSERT INTO my_table (user_id, kyc_info, todo_info) VALUES ("u123","客户信息","笔记")
ON DUPLICATE KEY UPDATE kyc_info= "客户信息", todo_info="笔记";

当插入session_id这个唯一索引重复的记录的时候,更新kyc_infotodo_info,如果是新记录,就直接插入。

其实这就相当于

-- 如果session_id相同代表是同一次会话,需求是笔记以会话为单位,一次会话不管怎么保存只能有一个笔记。
UPDATE 表名 SET kyc_info="客户信息",  todo_info="笔记" WHERE session_id="huihua123";

直接运行上面这个sql一点问题都没有,那简直看起来正确极了,但是用到mybatis,就一直报错

    <insert id="insertOrUpdateByPrimaryKeySelective" parameterType="你的entity实体对象">
        insert into 表名
        <trim prefix="(" suffix=")" suffixOverrides=",">
          <if test="userId!= null">
            user_id,
          </if>
          <if test="kycInfo!= null">
            kyc_info,
          </if>
          <if test="todoInfo!= null">
            todo_info,
          </if>
        </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
          <if test="userId!= null">
            #{userId,jdbcType=VARCHAR},
          </if>
          <if test="kycInfo!= null">
            #{kycInfo,jdbcType=VARCHAR},
          </if>
          <if test="todoInfo!= null">
            #{todoInfo,jdbcType=VARCHAR},
          </if>
        </trim>
        ON DUPLICATE KEY UPDATE
        kyc_info= #{kycInfo,jdbcType=VARCHAR},
        todo_info=#{todoInfo,jdbcType=VARCHAR}
    </insert>

结果一直报错:

SQLException: No value specified for parameter 4

你甚至惊奇的发现你只传了3个参数却提示没找到第4个参数。

问题出在这里

        ON DUPLICATE KEY UPDATE
        kyc_info= #{kycInfo,jdbcType=VARCHAR},
        todo_info=#{todoInfo,jdbcType=VARCHAR}

你应该写成

        ON DUPLICATE KEY UPDATE
        kyc_info= values(kyc_info),
        todo_info=values(todo_info)

结果就正确了。

综上,sql语句就应该写成
insert into 表名(字段1,字段2,...) values(值1, 值2,...) on duplicate key update 字段1=values(字段1), 字段2=values(字段2)
而不是
insert into 表名(字段1,字段2,...) values(值1, 值2,...) on duplicate key update 字段1=值1, 字段2=值2...

后者只有sql单独运行可以,mybatis运行报错。

前者不管单独运行还是mybatis执行都是ok

所以下面就不推荐这么写

INSERT INTO my_table(user_id, kyc_info, todo_info) VALUES ("u123","客户信息","笔记")
ON DUPLICATE KEY UPDATE kyc_info= "客户信息", todo_info="笔记";

推荐写法如下:

INSERT INTO my_table(user_id, kyc_info, todo_info) VALUES ("u123","客户信息","笔记")
ON DUPLICATE KEY UPDATE kyc_info= values(kyc_info), todo_info=values(todo_info);

亲身经历什么叫一个bug找一天。老铁们点点关注,给你们踩坑了!



欢迎一键三连~



有问题请留言,大家一起探讨学习



----------------------Talk is cheap, show me the code-----------------------

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
1天前
|
SQL 存储 关系型数据库
MySQL进阶突击系列(01)一条简单SQL搞懂MySQL架构原理 | 含实用命令参数集
本文从MySQL的架构原理出发,详细介绍其SQL查询的全过程,涵盖客户端发起SQL查询、服务端SQL接口、解析器、优化器、存储引擎及日志数据等内容。同时提供了MySQL常用的管理命令参数集,帮助读者深入了解MySQL的技术细节和优化方法。
|
2天前
|
SQL Oracle 关系型数据库
SQL(MySQL)
SQL语言是指结构化查询语言,是一门ANSI的标准计算机语言,用来访问和操作数据库。 数据库包括SQL server,MySQL和Oracle。(语法大致相同) 创建数据库指令:CRATE DATABASE websecurity; 查看数据库:show datebase; 切换数据库:USE websecurity; 删除数据库:DROP DATABASE websecurity;
|
25天前
|
SQL 缓存 Java
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
本文详细介绍了MyBatis的各种常见用法MyBatis多级缓存、逆向工程、分页插件 包括获取参数值和结果的各种情况、自定义映射resultMap、动态SQL
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
|
2月前
|
SQL 运维 关系型数据库
MySQL 运维 SQL 备忘
MySQL 运维 SQL 备忘录
48 1
|
1月前
|
SQL 关系型数据库 MySQL
MySql5.6版本开启慢SQL功能-本次采用永久生效方式
MySql5.6版本开启慢SQL功能-本次采用永久生效方式
38 0
|
1月前
|
SQL 关系型数据库 MySQL
mysql编写sql脚本:要求表没有主键,但是想查询没有相同值的时候才进行插入
mysql编写sql脚本:要求表没有主键,但是想查询没有相同值的时候才进行插入
31 0
|
2月前
|
SQL 存储 关系型数据库
mysql 数据库空间统计sql
mysql 数据库空间统计sql
47 0
|
2月前
|
SQL 存储 关系型数据库
mysql SQL必知语法
本文详细介绍了MySQLSQL的基本语法,包括SELECT、FROM、WHERE、GROUPBY、HAVING、ORDERBY等关键字的使用,以及数据库操作如创建、删除表,数据类型,插入、查询、过滤、排序、连接和汇总数据的方法。通过学习这些内容,读者将能更好地管理和操
22 0
|
3月前
|
关系型数据库 MySQL 网络安全
5-10Can't connect to MySQL server on 'sh-cynosl-grp-fcs50xoa.sql.tencentcdb.com' (110)")
5-10Can't connect to MySQL server on 'sh-cynosl-grp-fcs50xoa.sql.tencentcdb.com' (110)")
|
5月前
|
SQL 存储 监控
SQL Server的并行实施如何优化?
【7月更文挑战第23天】SQL Server的并行实施如何优化?
119 13