不是国产数据太坑,我才是小丑!

1,042 阅读3分钟

前言

学了10年的编程了,直到此时此刻才发现我连一个查询语句 都没搞清楚过🙈

先看一个SQL👴 :

-- tips: `create_by` 是 `vachar` 类型  ,数据库为 mysql
SELECT distinct create_by FROM t_msg WHERE create_by = 116;

心里有答案了吗❔:

image.png

看看输出结果吧:

image.png

一不定不是只有我一个人惊讶吧! 告诉我,你们都不知道为啥😁

国产数据之坑

问题描述

昨天发生了一件诡异的事儿,生产环境的日志出现这个错误无效的类型 integer 输入语法: "028-888812",当时看了接口,传的参数是1xxxx呀,为啥为出现一个028-xx的号码呢。

image.png

排查过程

  1. 当时也是百思不得其解,难道是 入参在哪个地方被修改了,看了代码中途没有修改参数!
  2. 可能是类型转换的问题(phone 数据库是vachar,mapper 传的参数是long),另一个类似的SQL也是这样写的,传的是long,就能正常运行。拿到数据库里面直接执行一下SELECT * FROM "user" WHERE "phone" = to_char(123456789),也能查询到结果呀🙈,结果中也没有028-xx呀!
  3. debug 拿到已经注入参数后的SQL,注意❗最后一个参数是没有 ' 号的.

image.png

把编译好的SQL,拿到管理工具里面执行,确实复现了:

image.png

看到这儿,我已经开启狂喷国产库了。什么玩意啊,竟然这么辣鸡。 就算类型不对,强转之后最多是牺牲性能啊,为啥会报错呢。

原来我才是小丑

当然,解决这个问题很简单,参数改成字符串的类型就行了。

当我还沉浸在又发现一个国产库的巨坑的喜悦之中的时候,看见一位抖音老哥的留言!

3f4d539d9ad002d70bffb4109ebd673.jpg

我🤦‍♂️ 明悟了✈,我一直以为类型转换是 where num = To_char(1234) , 没想类型转换可能是这种情况呢 where to_char(num) = 123

是把字符串 这一列 转成 数字,然后再对比,这样遇到转不成数字的就报错,这个逻辑刚好能解释了这个报错。

验证一下:explain 看看执行计划

image.png

原来就是这样啊,把数据库列数据转成数字。
😲没想到啊!原来我才是小丑,原来是我对类型转换的理解一直有误😂

知识扩展

看来得AI一下类型转换的逻辑了,学了10年编程,才发现原来自己对类型转换的理解一直有问题!

MySQL

  • 转换逻辑:MySQL 会尝试将 VARCHAR 类型的 phone 字段值转换为数字类型,然后再与 123 进行比较。在转换过程中,MySQL 会从字符串的开头开始解析数字,直到遇到非数字字符为止。如果字符串开头没有有效的数字,那么转换结果为 0

如下就是前言中的例子:

image.png

PostgreSQL(Oracle )

  • 转换逻辑:PostgreSQL 会尝试将数字 123 转换为 VARCHAR 类型,然后再与 phone 字段的值进行比较。转换时,数字会被直接转换为对应的字符串表示形式。 (❗没测过❗)

KingBase

会尝试将 VARCHAR 类型的 phone 字段值转换为数字类型,然后再与 123 进行比较,转不出来就报错。(如果参数比较小,就转Integer,否则转Bigint. 报错还可能出现 is out of range for type XXimage.png