cast基本写法为cast(expression as target_type),需注意类型名差异(如postgresql用integer、sql server用int)、日期格式兼容性、数值截断规则及where中使用导致索引失效等问题。

CAST函数的基本写法和常见错误
SQL里CAST不是万能胶,不能随便往字段上糊——它只在支持显式类型转换的数据库中有效,且语法稍有差异。PostgreSQL、SQL Server、MySQL 8.0+、SQLite 都支持标准写法:CAST(expression AS target_type);但MySQL 5.7及更早版本对某些目标类型(比如DATE)不支持直接CAST,得用STR_TO_DATE等替代。
最常踩的坑是漏掉括号或写错类型名:比如写成 CAST(col AS INT) 在 PostgreSQL 会报错,必须写 INTEGER;而 SQL Server 接受 INT,但不接受 STRING(得用 VARCHAR 或 NVARCHAR)。
- 表达式必须可求值,不能是空字符串转数字(
CAST('' AS INTEGER)在多数库中直接报错) - 目标类型要带长度或精度时,不同库写法不同:PostgreSQL 支持
CHAR(10),SQL Server 要写CHAR(10),但 SQLite 忽略长度 - NULL 值可以被正常转换,不会报错,结果仍是 NULL
把字符串转成日期/时间时的兼容性问题
这是CAST最容易翻车的场景。字符串格式必须严格匹配目标类型的默认解析规则,否则直接失败——CAST('2023-01-01 14:30' AS DATE) 在 PostgreSQL 和 SQL Server 中成功,但在 MySQL 中可能被截断或报错,尤其当字段含毫秒、时区或非标准分隔符(如'01/01/2023')时。
- PostgreSQL 对格式宽容,能识别多种常见格式,但
CAST('01-01-2023' AS DATE)默认按 MDY 解析,可能出错 - SQL Server 依赖当前会话的
DATEFORMAT设置,SET DATEFORMAT DMY后才能正确解析'01/02/2023' - MySQL 更建议用
STR_TO_DATE(col, '%Y-%m-%d')代替CAST,可控性强
如果数据来源不可控,先用TRY_CAST(SQL Server)或TO_DATE(PostgreSQL)兜底,避免查询中断。
数字类型转换中的精度丢失和溢出
CAST做数值降级(比如DECIMAL(10,4) → INTEGER)会截断小数部分,不是四舍五入;升精度(INTEGER → DECIMAL(5,2))则补零。但溢出时行为不一:SQL Server 抛Arithmetic overflow error,PostgreSQL 返回ERROR: numeric field overflow,而 MySQL 可能静默转成最大值(取决于 SQL mode)。
-
CAST(999.999 AS INTEGER)结果是999(截断),不是1000 -
CAST(12345 AS TINYINT)在 SQL Server 中直接报错(TINYINT 范围 0–255) - 想保留小数并四舍五入,先用
ROUND()再CAST,例如:CAST(ROUND(999.999, 0) AS INTEGER)
在WHERE或JOIN中用CAST的性能隐患
在过滤条件或关联字段上套CAST,大概率导致索引失效——因为数据库无法用原始索引去匹配转换后的值。比如WHERE CAST(order_id AS VARCHAR) = '12345',即使order_id是整型且有索引,优化器也很难走索引扫描。
- 优先改写为类型一致的比较:
WHERE order_id = 12345(而不是转字符串) - 若必须转换(如关联字符串ID和数字ID表),考虑在冗余字段上建计算列索引(SQL Server)或函数索引(PostgreSQL:
CREATE INDEX ON t ((CAST(id AS TEXT)))) - 在 GROUP BY 或 ORDER BY 中用
CAST也可能拖慢排序,特别是大数据集
真正麻烦的不是语法怎么写,而是你永远不知道下游数据库是不是悄悄把你的CAST当成了全表扫描的触发器。











