mysql 诡异的1054错误

2023-05-16

前言

今天在工作中遇到一个非常坑爹的问题,有关Mysql的异常处理,花费了我好几个小时的时间,最后终于解决了,然后根据出现的问题的原因,逆向来看自己解决问题的过程,发现网上的一些文章简直是太坑了,坑的人找不着北啊,最后总结一下吧,免得又踩到这个坑。

先交代一下环境和背景:问题出现在工作的项目中,工程代码在运行的过程中会调用事先定义好的存储过程来保存数据,因为字段太多,大概有好几百个,我就想着把一些废弃的字段删掉,这样一来可以加快存储速度,二来减小数据库的存储大小,于是说干就干,为了避免不必要的麻烦,我决定先改存储过程,在参数中去想不需要存储的字段, 等检测没有问题了再删除表中的字段,就当我改完的时候问题出现了,数据存不上了…

分析过程

是的,数据存不上了,但是程序不报错,理论上如果调用存储过程失败了,程序会打印出错误代码,比如:1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'xxx' at line 1,但是并没有,我是通过存储过程中的异常打印发现错误的,就是这一句DECLARE EXIT HANDLER FOR SQLEXCEPTION CALL LogError("SetBaseData:SQLEXCEPTION");,存储过程中如果有这一句,当发生异常的时候就可以调用自定义函数LogError("SetBaseData:SQLEXCEPTION")来将错误信息打印到数据库中,可是程序代码为什么不报错呢?这我就想不明白了。

还是想来先来看一下存储过程的示例:

CREATE PROCEDURE SetBaseData(
  IN paramId INT,
  IN paramA INT,
  IN paramB INT,
  IN paramC INT,
  IN paramD INT,
  IN paramE INT,
  IN paramF INT,
  IN paramG INT
)
BEGIN
  DECLARE EXIT HANDLER FOR SQLEXCEPTION CALL LogError("SetBaseData: SQLEXCEPTION");
  UPDATE dataT SET
    A=paramA,
    B=paramB,
    C=paramC,
    D=paramD,
    E=paramE,
    F=paramF,
    G=paramG,
  WHERE Id=paramId; 
END; 

看了这个存储过程是不是感觉很简单,结构是很简单,但是实际的存储过程中可是有好几百个字段需要修改,所以很难查到问题,结果问题就出在我精简字段的过程中,比如我删除无用的字段改成了下面这个样子:

CREATE PROCEDURE SetBaseData(
  IN paramId INT,
  IN paramA INT,
  IN paramB INT,
  IN paramE INT,
  IN paramG INT
)
BEGIN
  DECLARE EXIT HANDLER FOR SQLEXCEPTION CALL LogError("SetBaseData: SQLEXCEPTION");
  UPDATE dataT SET
    A=paramA,
    B=paramB,
    E=paramE,
    F=paramF,
    G=paramG,
  WHERE Id=paramId; 
END; 

怎么样,发现问题了吗?这样小一个存储过程应该一眼就能发现问题,paramF参数已经删掉了,但是在Update语句中还在使用,这就能解释为什么会触发异常导致数据无法存储了,但是想在几百个字段中找出这样的问题真的很困难,并且参数的顺序和设置的顺序是不一样的,一开始我也没发现,只能在异常结果上分析,有人可能会问我为什么不在程序中下断点,虽然没有打印信息,但是看返回值总能发现问题吧,很遗憾,底层代码被封装了,我只能看到返回了错误的结果,但是却分辨不出是什么错误,奇就奇怪在这,原来存储过程返回错误都是有打印信息的啊。

既然代码看不到,我就只能从存储过程中找原因了,于是我想到使用更细化的异常处理,但是找了半天也不能直接输出异常类型,只能单个捕获,于是上网查了错误代码的分类,发现网上千篇一律的都是下图中的错误代码总结,这正是坑人的地方,其实就是抄来的。

Mysql error

于是我对着这些错误代码挨个检测把存储过程改成了这样:

CREATE PROCEDURE SetBaseData(
  IN paramId INT,
  IN paramA INT,
  IN paramB INT,
  IN paramE INT,
  IN paramG INT
)
BEGIN
  DECLARE EXIT HANDLER FOR 1021 CALL LogError("1021 ");
  DECLARE EXIT HANDLER FOR 1022 CALL LogError("1022 ");
  DECLARE EXIT HANDLER FOR 1027 CALL LogError("1027 ");
  DECLARE EXIT HANDLER FOR 1036 CALL LogError("1036 ");
  DECLARE EXIT HANDLER FOR 1048 CALL LogError("1048 ");
  DECLARE EXIT HANDLER FOR 1062 CALL LogError("1062 ");
  DECLARE EXIT HANDLER FOR 1099 CALL LogError("1099 ");
  DECLARE EXIT HANDLER FOR 1100 CALL LogError("1100 ");
  DECLARE EXIT HANDLER FOR 1104 CALL LogError("1104 ");
  DECLARE EXIT HANDLER FOR 1106 CALL LogError("1106 ");
  DECLARE EXIT HANDLER FOR 1114 CALL LogError("1114 ");
  DECLARE EXIT HANDLER FOR 1150 CALL LogError("1150 ");
  DECLARE EXIT HANDLER FOR 1165 CALL LogError("1165 ");
  DECLARE EXIT HANDLER FOR 1242 CALL LogError("1242 ");
  DECLARE EXIT HANDLER FOR 1263 CALL LogError("1263 ");
  DECLARE EXIT HANDLER FOR 1264 CALL LogError("1264 ");
  DECLARE EXIT HANDLER FOR 1265 CALL LogError("1265 ");
  DECLARE EXIT HANDLER FOR 1312 CALL LogError("1312 ");
  DECLARE EXIT HANDLER FOR 1317 CALL LogError("1317 ");
  DECLARE EXIT HANDLER FOR 1319 CALL LogError("1319 ");
  DECLARE EXIT HANDLER FOR 1325 CALL LogError("1325 ");
  DECLARE EXIT HANDLER FOR 1326 CALL LogError("1326 ");
  DECLARE EXIT HANDLER FOR 1328 CALL LogError("1328 ");
  DECLARE EXIT HANDLER FOR 1329 CALL LogError("1329 ");
  DECLARE EXIT HANDLER FOR 1336 CALL LogError("1336 ");
  DECLARE EXIT HANDLER FOR 1337 CALL LogError("1337 ");
  DECLARE EXIT HANDLER FOR 1338 CALL LogError("1338 ");
  DECLARE EXIT HANDLER FOR 1339 CALL LogError("1339 ");
  DECLARE EXIT HANDLER FOR 1348 CALL LogError("1348 ");
  DECLARE EXIT HANDLER FOR 1357 CALL LogError("1357 ");
  DECLARE EXIT HANDLER FOR 1358 CALL LogError("1358 ");
  DECLARE EXIT HANDLER FOR 1362 CALL LogError("1362 ");
  DECLARE EXIT HANDLER FOR 1363 CALL LogError("1363 ");
  DECLARE EXIT HANDLER FOR SQLEXCEPTION CALL LogError("SetBaseData: SQLEXCEPTION");
  UPDATE dataT SET
    A=paramA,
    B=paramB,
    E=paramE,
    F=paramF,
    G=paramG,
  WHERE Id=paramId; 
END; 

看到这里是不是觉得我丧心病狂,确实是,但是我没有办法了啊,可是事与愿违,这么狠毒的代码最终也没有捕获到错误,可见网上的常见错误代码其实没什么卵用,接下来我就想既然代码中不打印错误,那么我直接在Mysql客户端调用存储过程总行了吧,一开始没这么做主要是字段太多了,好几百个呀,现在没办法了,只能试一试我对照着参数的类型,一个个输入,最后call运行存储过程,诡异的事情发生了,没有任何报错,甚至警告都没有,但是数据还是没有保存上,简直要疯了。没办法最终只能一行一行的看存储过程的定义了,那可是好几百行啊,这种定义和C++代码不同,根本就没有跳转,只能靠脑袋记忆,我又没用IDE,只能硬着头皮看了,还好功夫不负有心人,最后让我发现了问题,就是paramF参数已经删掉了,但是在Update语句中还在使用这样的情况,于是我改正了过来,发现保存数据没有问题了。

可是我那么多捕获异常的代码就白写了吗?于是我又还原了回去,结果令人震惊的一幕发生了,程序就然报错了,就是我刚才改过的那一句,1054 - Unknown column 'paramF' in 'field list',你说奇不奇怪,我都找到问题了,你居然又明确的指出来了,早干嘛去了,不过这条消息还算有点用,起码让我知道这是”1054异常”啊,于是我把这个异常在存储过程中做了处理,加了一句DECLARE EXIT HANDLER FOR 1054 CALL LogError("1054 ");这次果然在调试信息中发现了这个错误,于是上网查了一下1054的含义,就是说某个变量没有出现在参数列表中.

为此我还查了一下Mysql的官网,发现Mysql的官网上列举了错误1002到4531总共有3000多个,看来网上的Mysql常见错误代码并不常见。

总结

  1. 通过这件事让我再一次发现代码的诡异
  2. 遇到问题还得相信自己,还是自己最靠谱
  3. 网上查资料要注意甄别,我发现网上流传的常见错误代码中连“1064 sql 语法错误”都没有包含,看来它并不常见
  4. 还是想直接在存储过程中输出异常的类型,不想一个个的捕获,我还没找到方法,希望有经验的大神能给我一点点指导。

附注

我还是把Mysql官网指出的错误贴在这:Mysql Error Codes

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

mysql 诡异的1054错误 的相关文章

  • 通过连接从两个表中删除?

    我有两个表如下 tbl1 tbl2 id article id title image whole news tags author older datetime 其中 tbl1 id gt tbl2 article id 如何从两个表中删
  • 单行的总和值?

    我有一个 MySQL 查询 它返回由一系列 1 和 0 组成的单行 它用于进度条指示器 我现在在代码中对它进行求和 但我尝试对查询中的值求和 并意识到我无法使用 SUM 因为它们有很多列 但只有一行 有没有办法可以在查询中自动求和 就像这样
  • 如何以最少的查询次数获取帖子列表和关联标签

    我的表格结构如下 标签 更多的是一个类别 id 标签名称 描述 slug POSTS ID 标题 网址 邮戳 id idPost idTag USERS ID 用户名 userSlug VOTES id idPost idUser 每个帖子
  • 将记录分成两列

    我的数据库中有一个 学生 表 其中包含大约 5 000 条记录 我想将这些记录显示在two分区 如何在不执行查询两次的情况下做到这一点 仅使用单个查询 显示示例http www freeimagehosting net uploads f1
  • MySql 最后插入 ID,连接器 .net

    我正在使用 MySql Connector net 我需要获取最后一个查询生成的插入 id 现在 我假设返回值是MySqlHelper ExecuteNonQuery应该是最后一个插入id 但它只返回1 我正在使用的代码是 int inse
  • 显示表 FULLTEXT 索引列

    我希望运行一个查询 该查询将返回表中全文索引的列列表 该表采用 MyISAM 格式 我将使用 php 来构建查询 理想情况下 我会运行查询 它会返回信息 以便我可以构造一个以逗号分隔的列字符串 例如 名 姓 电子邮箱 这在 MySQL 中可
  • PDO SQLSRV 和 PDO MySQL 在获取 int 或 float 时返回字符串

    当您获取时 PDO MS SQL Server 和 PDO MySQL 都会返回一个字符串数组 即使列的 SQL 类型本应是数字类型 例如 int 或 float 我设法解决了这个问题 但我想了解为什么它们一开始就这样设计 是不是因为PDO
  • 无法启动 MySQL 服务器 - 控制进程退出并出现错误代码

    我的 mysql 服务器停止后无法启动 命令使用 sudo etc init d mysql restart Error 重新启动 mysql 通过 systemctl mysql serviceJob for mysql service
  • java mysql 准备好的语句

    我正在尝试使用 java 向数据库中进行简单的插入 它告诉我我的 sql 语法已关闭 但是 当我复制打印出来的字符串并将其放入 phpmyadmin 中的 sql 命令中时 它会正确执行该命令 并且我似乎无法弄清楚 java 中的字符串查询
  • 当sql连接中存在两个同名列时,如何从一个表列中获取值

    当我连接两个具有相同名称列的表时 我目前面临着尝试获取值的问题 例如 table1 date和table2 date 每个表中的日期不同 我将如何获取 日期 本例中的表1 我目前正在跑步 while row mysqliquery gt f
  • Mysql 检索所有有限制的行

    我想检索特定用户的所有行 限制为 0 x 所以我只是想问是否有任何方法可以检索 mysql 中的所有行 而不调用返回 x 的 count id 的方法 而不重载现有函数 该函数在查询中根本没有限制 与我们的 string Relace 功能
  • 为什么我的 if 语句没有按我预期的方式工作?

    我正在尝试实现以下目标 我向我的 SQL 数据库询问使用SELECT FROM subjects 这样做之后我要求使用数组mysqli fetch assoc 在那之前一切都很好 现在的问题是 当我尝试在每个循环中修改 genero 的值
  • 在 MySQL 中使用 COUNT 时如何返回 0 而不是 null

    我使用此查询返回存储在 sTable 中的歌曲列表以及存储在 sTable2 中的总项目数 SQL queries Get data to display sQuery SELECT SQL CALC FOUND ROWS str repl
  • MySQL连接字符集问题

    我在 Mac 上使用带有 MySQL 的 velosurf 没有任何编码问题 但是当我切换到 Linux 计算机时 从 velosurf 获得的值未正确编码 我发现这可能是默认连接字符集的问题 在 Mac 上我得到 mysql gt sho
  • 即使使用“autoReconnect=true”,MySql JDBC 也会超时[重复]

    这个问题在这里已经有答案了 有时 我的 Java Tomcat6 Debian Squeeze 应用程序无法与 MySql 服务器通信 Tomcat 应用程序位于前端服务器上 而 MySql 位于单独的 仅限 MySql 的机器上 一个典型
  • 如何使用 Perl 更改 mysql 密码

    我需要使用 Perl 脚本更改一些 mysql 密码 以下内容在更改数据库条目时有效 但是当我针对 mysql 用户更改修改它时 它将它们重置为空白密码 最后 刷新权限 也很好 但我还没有找到方法 usr bin perl use DBI
  • Bugzilla 中分离客户端的基本权限

    我正在尝试配置一个 Bugzilla 实例 这将允许我的客户登录并为其正在开发 维护的网站提交错误 例如 我创建了 2 个名为 TestProject TestProject2 的产品和一个名为 TestClient 的用户 我想要实现的是
  • 如何在 Play java 中创建数据库线程池并使用该池进行数据库查询

    我目前正在使用 play java 并使用默认线程池进行数据库查询 但了解使用数据库线程池进行数据库查询可以使我的系统更加高效 目前我的代码是 import play libs Akka import scala concurrent Ex
  • 映射 mysql 中同一个表的多个值

    您好 我必须使用另一个表中的值 id 获取文本值 表 1 包含值 ID 表 2 包含名称和值 ID 表 1 SEVERITY OCCURENCE DETECTABILITY 2 3 4 表 2 id name value 1 Very Hi
  • 如何修改现有表以添加时区

    我有一个包含 500 多个表的大型应用程序 我必须将应用程序转换为时区感知 当前应用程序使用new java util Date GETDATE 与服务器的时区 即没有任何时区支持 我已将这项任务分为几个步骤 以便于开发 我确定的第一个步骤

随机推荐

  • mavros安装流程(超简单)

    只适用于Ubuntu18 04 在Ubuntu中新建一个空白文本 xff0c 命名为123 sh bin bash Bash script for setting up ROS Melodic with Gazebo 9 developme
  • 安装WSL2+Ubuntu18.04(慢慢更新记录)

    1 安装WSL和Ubuntu WSL官网在此 安装 WSL Microsoft Learn Windows下CMD xff0c 先安装WSL2 wsl install 然后进入Microsoft Store xff0c 搜索Ubuntu然后
  • -bash: ./Setup.sh: Permission denied

    sudo chmod 777 xxx
  • Linux 给文件夹或者文件添加权限

    chmod R 777 文件夹 参数 R是递归的意思 777表示开放所有权限 chmod 777 test sh chmod 43 x 某文件 如果给所有人添加可执行权限 xff1a chmod a 43 x 文件名 xff1b 如果给文件
  • Postman使用笔记——Postman发送get请求

    前言 在实际的开发当中 xff0c 我们经常用到get或者post请求 在这篇博客里面分享一下 xff0c 如何在Postman中发送get请求 发送get请求 1 在Postman工作空间选定get请求 图中我们可以看到很多请求方式 xf
  • jdbc连接mysql数据库的详细步骤

    标题 jdbc连接mysql数据库 1 首先在项目根目录创lLib文件夹 xff0c 放入jdbc驱动程序 xff0c 然后Add As Library 2 建包 bean包 xff1a 专门放置属性类 dao包 xff1a 进行数据操作的
  • css高度从0到auto的transition动画

    如题 xff0c 想实现css高度从0到auto的transition动画 xff0c 发现直接写没有效果 查了一下 xff0c 发现可以用max height解决 xff0c 代码如下 lt DOCTYPE html gt lt html
  • beego打包

    beego打包 在main go 对应的目录下 windows平台 xff1a bee pack be GOOS 61 windows 打包后生成一个tar gz文件 xff0c 发送到部署服务器 xff0c 解压gz为tar xff0c
  • C++求解组合数的具体实现

    文章目录 前言问题起因组合公式公式变形递推公式递归实现备忘递归动态规划压缩DP其他优化 总结补充反向递归正向递推 前言 很少写关于具体算法的总结笔记 xff0c 因为很难把一个算法从头到尾的叙述清晰并且完整 xff0c 容易造成误解 这次想
  • protobuf中SerializeToString和SerializePartialToString的区别

    文章目录 前言proto2message定义message扩展注意事项 proto3序列化SerializeToString和SerializeAsString区别SerializeToString和SerializePartialToSt
  • epoll的LT模式(水平触发)和ET模式(边沿触发)

    文章目录 前言名称的记忆状态变化LT模式ET模式数据的读取和发送代码实践基础代码测试分类怎么解决ET触发了一次就不再触发了 总结 前言 epoll的触发模式是个引发讨论非常多的话题 xff0c 网络上这方面总结的文章也很多 xff0c 首先
  • 参考开源项目实现一个简易的C++枚举转字符串的函数

    文章目录 前言改造函数使用各函数的作用总结 前言 前段时间接触了 magic enum 这个开源库 xff0c 代码量不算太多 xff0c 是一个但头文件的枚举操作库 xff0c 关于如何使用还写了一篇总结 推荐一个C 43 43 枚举转字
  • SVN通过备份、过滤、再导入的方式彻底删除废弃目录

    文章目录 前言简要步骤操作示例总结 前言 SVN占用的空间随着项目版本迭代越来越大 xff0c 因为保存了历史记录中的各个版本 xff0c 所以即使本地把废弃的目录删掉提交 xff0c 也不会释放出多余的空间 xff0c 大概率因为操作删除
  • Nginx返回静态的json字符串

    文章目录 前言修改配置文件返回简单json字符串返回json文件内容 总结 前言 自从上次安装完nginx我把服务器对外开发的端口都通过它来转发了 xff0c 真香 xff0c 最近要加一个获取最新版本号的功能 xff0c 一开始还想写在服
  • 前端笔记25——CSS子元素选择器

    前言 前面分享了后代选择器 xff0c 下面分享一下学到的子元素选择器 子元素选择器 子元素选择器是指选择符合条件的子元素 xff0c 需要运用到 gt 符号 xff0c 下面通过实例来看一下 xff1a lt DOCTYPE html g
  • linux下使用dd命令测试磁盘的读写速度

    文章目录 前言D状态进程dd命令问题原因总结 前言 最近打包更新总是特别慢 xff0c 其中有一步使用md5sum命令计算MD5值的操作有时居然要卡一个小时 xff0c 虽说计算MD5比较耗时 xff0c 但通常计算5个G数据的md5值也就
  • .bat批处理(二):%0 %1——给批处理脚本传递参数

    文章目录 前言内容总结 前言 初次接触批处理脚本觉得有点意思 xff0c 所以决定写一个小功能试验一下 xff0c 谁知刚一开始就发现遇到了麻烦 xff0c 本想着使用参数来控制程序的运行结果 xff0c 可是参数怎么传进去呢 xff0c
  • .bat批处理(三):变量声明、设置、拼接、截取

    文章目录 前言内容总结 前言 在使用批处理脚本的时候我们常常会有这类需求 xff0c 比如需要设置一个变量来存储数据 xff0c 简化程序书写 xff1b 拼接现有的内容得到新的变量 xff1b 截取变量的一部分来满足我们的要求 xff0c
  • ... fatal error LINK1120:1个无法解析的外部命令 的解决办法

    前言 首先说这是一个链接错误而不是编译错误 xff0c 造成这种问题的根本原因就是找得到函数的声明 xff0c 但是找不到函数的实现 xff0c 这是最根本的 xff0c 具体的表现形式有很多 xff0c 我们稍后再做分析 xff0c 下面
  • mysql 诡异的1054错误

    前言 今天在工作中遇到一个非常坑爹的问题 xff0c 有关Mysql的异常处理 xff0c 花费了我好几个小时的时间 xff0c 最后终于解决了 xff0c 然后根据出现的问题的原因 xff0c 逆向来看自己解决问题的过程 xff0c 发现