如果 ORDER BY 的列是字符串类型(如 VARCHAR)但存的是数字,排序会按字典序而不是数值大小。
-- num_str 列值:'1','10','2','20'SELECT num_str FROM t ORDER BY num_str; -- '1','10','2','20' (字典序)SELECT num_str FROM t ORDER BY CAST(num_str AS UNSIGNED); -- '1','2','10','20'
4. 常用业务场景中的类型转换
4.1 将存储为字符串的数字用于数值排序或计算
-- 正确排序SELECT * FROM products ORDER BY CAST(price_str AS DECIMAL(10,2));-- 计算总和SELECT SUM(CAST(amount_str AS UNSIGNED)) FROM payments;
4.2 数字补零 / 格式化
-- 订单编号:'ORD' + 6位流水号SELECT CONCAT('ORD', LPAD(CAST(id AS CHAR), 6, '0')) AS order_noFROM orders;-- 如果 id 是数字,LPAD 会隐式转为字符串
4.3 提取字符串中的数字并转换为数值
-- MySQL 8.0 正则提取并转换SELECT CAST(REGEXP_SUBSTR('楼层15-16室', '[0-9]+') AS UNSIGNED) AS floor;-- 结果为 15
4.4 安全处理空值或无效值
-- 如果字段可能为 NULL 或非数字,计算时给默认值SELECT IFNULL(CAST(score AS SIGNED), 0) FROM exams;-- 或者用 CASE 判断SELECT CASE WHEN score REGEXP '^[0-9]+$' THEN CAST(score AS SIGNED) ELSE 0 ENDFROM exams;
4.5 判断字符串能否转为日期,并转换
-- 尝试转为日期,如果失败则返回 NULLSELECT IF(STR_TO_DATE(date_str, '%Y-%m-%d') IS NULL, NULL, CAST(date_str AS DATE))FROM raw_data;-- 或者直接用 STR_TO_DATESELECT STR_TO_DATE(date_str, '%Y-%m-%d') FROM raw_data; -- 无法转换返回 NULL
4.6 JSON 字段值提取并转换类型
SELECT JSON_UNQUOTE(JSON_EXTRACT(extra, '$.age')) AS age_str, CAST(JSON_UNQUOTE(JSON_EXTRACT(extra, '$.age')) AS UNSIGNED) AS age_intFROM profiles;-- MySQL 5.7.8+ 也可使用 ->> 操作符SELECT extra->>'$.age' AS age_str, CAST(extra->>'$.age' AS UNSIGNED) AS age_intFROM profiles;
4.7 字符串比较忽略大小写(通过字符集转换实现)
SELECT * FROM users WHERE CONVERT(username USING utf8mb4) = 'admin';-- 或者使用 COLLATE,更规范
4.8 二进制与字符串互转
-- 字符串转二进制(如存储哈希值)SELECT UNHEX(SHA2('hello', 256));-- 二进制转可读字符串SELECT HEX(binary_field) FROM t;
4.9 避免隐式转换带来的”诡异”结果
-- 错误:'a' 被转为 0,导致 WHERE 条件为真SELECT * FROM t WHERE 0 = 'a'; -- 返回所有行!-- 正确做法:使用 CAST 或显式类型确保类型一致SELECT * FROM t WHERE CAST(col AS UNSIGNED) = 0;
总结要点
类型判断多借助 REGEXP、ISNULL、STR_TO_DATE 等函数来间接实现。
显式转换使用 CAST(expr AS type) 或 CONVERT(expr, type),可使代码清晰、避免隐式陷阱。