上周接了个老项目迁移,时间字段存的是文本,排序全乱套,程序员小张问我能不能在查询里直接转类型。能,而且不用改表结构,查的时候现转就行,关键是分清你要转的是字符集还是数据类型。
转字符集和转类型是两码事
很多新手搜到这个词,以为只有一个功能,其实它有两副面孔。写在字段后面加字符集名的写法,是解决乱码的,比如把拉丁字符集转成通用编码,导出来的中文才不变成问号。另一种是指定目标类型的写法,专门对付文本存数字、文本存日期这种历史包袱,排序和比较瞬间正常。
文本数字比大小翻车的现场
订单号存成文本,查大于1000的记录,结果连90多都出来了,因为文本是按字典序比的。这时候在条件里把字段转成带符号整数再比,90多自然被过滤掉。金额字段同理,转成小数再求和,不然字符串相加会拼成一长串。记住转完只影响本次查询,原表数据不动手脚,胆子可以大一点。
日期字符串排序的救急办法
老系统喜欢用年月日连字符存日期,查某个月的数据,直接转成日期类型再比较,比截字符串靠谱得多。转完还能直接做差值,比如算两天相隔几天,不用再拉回代码里算。遇到空字符串会转成空值,记得加个判空,不然统计总数会少几条,对账时差一两条最难查。
三个容易踩的坑
目标类型名字写错会直接报错,整数、小数、日期、字符这几个最常用,别自己发明。超长文本转整数溢出后变成最大值,金额大时改用小数类型。字符集转换写反了会越转越乱,转之前先查清原表到底是什么编码,用错命令等于火上浇油。
- 乱码用字符集写法:先确认原编码,再往通用编码转
- 比大小用类型写法:文本数字一律先转数值再比较
- 上线前提醒:查询里转是救急,数据量大了还是要改表结构加索引
SELECT 转后(订单号 USING 通用编码) FROM 订单表SELECT * FROM 订单表 WHERE 转类型(订单号,带符号整数)大于1000SELECT * FROM 记录表 WHERE 转类型(日期串,日期)介于月初与月末之间SELECT 求和(转类型(金额串,小数)) FROM 账单表