结论:跨库兼容必须用cast,convert仅限sql server格式化输出;cast符合ansi标准,支持mysql 8.0+、postgresql、sql server、oracle;convert的style参数非通用,不可移植。

直接说结论:用 CAST 做跨库兼容的类型转换,用 CONVERT 在 SQL Server 里做带格式的日期/数字输出——别混着用,也别指望它能在 MySQL 或 PostgreSQL 里跑通。
什么时候必须用 CAST?
当你写的 SQL 要在多个数据库(比如开发用 PostgreSQL、上线用 SQL Server)之间迁移,或者被 ORM 自动生成时,CAST 是唯一安全的选择。它的语法 CAST(expr AS target_type) 是 ANSI SQL 标准,MySQL 8.0+、PostgreSQL、SQL Server、Oracle 全都认。
- 错误写法:
CONVERT(VARCHAR, '2023-01-01')—— 在 PostgreSQL 里直接报function convert(unknown, unknown) does not exist - 正确写法:
CAST('2023-01-01' AS DATE)—— 所有主流数据库都支持 - 注意目标类型的长度隐含规则:比如
CAST('hello world' AS CHAR(5))会截断为'hello',不是报错 - 遇到非法值(如
CAST('abc' AS INT))会直接中断查询,SQL Server 可改用TRY_CAST('abc' AS INT)返回NULL,但 MySQL 和 PostgreSQL 没这个函数
CONVERT 的 style 参数到底能干啥?
CONVERT 是 SQL Server 独有的,第三个参数 style 只对 DATE、DATETIME、MONEY 等少数类型生效,本质是“格式化输出”,不是类型转换本身。
-
CONVERT(VARCHAR, GETDATE(), 120)→'2026-04-20 10:01:00'(ISO 格式,带时间) -
CONVERT(VARCHAR, GETDATE(), 103)→'20/04/2026'(英国格式,注意服务器区域设置可能影响解析) -
CONVERT(VARCHAR, 12345.67, 1)→'12,345.67'(带千分位) - style 值不是通用编码:120 在 SQL Server 有效,在其他数据库毫无意义;且某些 style(如两位年份的 1 or 101)结果不确定,官方文档明确标为“不推荐”
- 别用
CONVERT去“解析”非标准日期字符串,比如CONVERT(DATE, '01-Apr-2026', 106)看似可行,但依赖语言环境,换服务器可能失败
字符串转数字总报错?先清理再转换
脏数据(空格、单位、N/A、混合文本)是 CAST 和 CONVERT 报错最常见原因。它们不做容错,遇到第一个非法字符就炸。
- SQL Server:用
TRIM()清空首尾空格,再套TRY_CAST,例如TRY_CAST(TRIM(age_str) AS INT) - PostgreSQL:用正则判断再转,
CASE WHEN age_str ~ '^\d+$' THEN age_str::INT END - MySQL 8.0+:没有
TRY_CAST,得靠CAST(IF(age_str REGEXP '^[0-9]+$', age_str, NULL) AS SIGNED) - 别依赖隐式转换“碰运气”:比如
WHERE date_col = '2026-04-20'看似能跑,但可能触发全表扫描或时区偏差(SQL Server 默认按本地时区解释无时区字符串)
精度和截断问题最容易被忽略
类型转换不是“看起来一样就行”,小数位、长度、四舍五入规则全由目标类型定义,而且不同数据库处理方式还不一样。
-
CAST('123.456' AS DECIMAL(5,2))在 SQL Server 和 PostgreSQL 中都会四舍五入成123.46,不是截断 -
CAST('123.456' AS DECIMAL(4,2))直接报错:精度不够,连小数点前三位都放不下 -
CONVERT(VARCHAR, 0xABCDEF, 1)输出'abcdef'(小写无前缀),而默认不加 style 是'0xABCDEF'—— 这个细节常被用来做十六进制清洗,但 style=1 并非所有版本都支持 - 日期转字符串后参与比较?别这么做。字符串比较是字典序,
'2026-01-01' > '2026-12-31'居然为真。该用日期类型就用日期类型
真正麻烦的从来不是语法怎么写,而是你没意识到:转换发生在哪一层(客户端?驱动?数据库?)、输入是否可信、目标类型是否真能容纳原始语义。多看执行计划里的隐式转换警告,比背函数手册有用得多。










