前言
学了10年的编程了,直到此时此刻才发现我连一个查询语句 都没搞清楚过🙈
先看一个SQL👴 :
-- tips: `create_by` 是 `vachar` 类型 ,数据库为 mysql
SELECT distinct create_by FROM t_msg WHERE create_by = 116;
心里有答案了吗❔:
看看输出结果吧:
一不定不是只有我一个人惊讶吧! 告诉我,你们都不知道为啥😁
国产数据之坑
问题描述
昨天发生了一件诡异的事儿,生产环境的日志出现这个错误无效的类型 integer 输入语法: "028-888812",当时看了接口,传的参数是1xxxx呀,为啥为出现一个028-xx的号码呢。
排查过程
- 当时也是百思不得其解,难道是 入参在哪个地方被修改了,看了代码中途没有修改参数!
- 可能是类型转换的问题(phone 数据库是vachar,mapper 传的参数是long),另一个类似的SQL也是这样写的,传的是long,就能正常运行。拿到数据库里面直接执行一下
SELECT * FROM "user" WHERE "phone" = to_char(123456789),也能查询到结果呀🙈,结果中也没有028-xx呀! debug拿到已经注入参数后的SQL,注意❗最后一个参数是没有'号的.
把编译好的SQL,拿到管理工具里面执行,确实复现了:
看到这儿,我已经开启狂喷国产库了。什么玩意啊,竟然这么辣鸡。 就算类型不对,强转之后最多是牺牲性能啊,为啥会报错呢。
原来我才是小丑
当然,解决这个问题很简单,参数改成字符串的类型就行了。
当我还沉浸在又发现一个国产库的巨坑的喜悦之中的时候,看见一位抖音老哥的留言!
我🤦♂️ 明悟了✈,我一直以为类型转换是 where num = To_char(1234) , 没想类型转换可能是这种情况呢 where to_char(num) = 123。
是把字符串 这一列 转成 数字,然后再对比,这样遇到转不成数字的就报错,这个逻辑刚好能解释了这个报错。
验证一下:explain 看看执行计划
原来就是这样啊,把数据库列数据转成数字。
😲没想到啊!原来我才是小丑,原来是我对类型转换的理解一直有误😂
知识扩展
看来得AI一下类型转换的逻辑了,学了10年编程,才发现原来自己对类型转换的理解一直有问题!
MySQL
- 转换逻辑:MySQL 会尝试将
VARCHAR类型的phone字段值转换为数字类型,然后再与123进行比较。在转换过程中,MySQL 会从字符串的开头开始解析数字,直到遇到非数字字符为止。如果字符串开头没有有效的数字,那么转换结果为0。
如下就是前言中的例子:
PostgreSQL(Oracle )
- 转换逻辑:PostgreSQL 会尝试将数字
123转换为VARCHAR类型,然后再与phone字段的值进行比较。转换时,数字会被直接转换为对应的字符串表示形式。 (❗没测过❗)
KingBase
会尝试将 VARCHAR 类型的 phone 字段值转换为数字类型,然后再与 123 进行比较,转不出来就报错。(如果参数比较小,就转Integer,否则转Bigint. 报错还可能出现 is out of range for type XX)