绝大多数场景下直接用 cast 更稳妥,因其语法统一、跨数据库兼容(postgresql、sql server、mysql 8.0+、sqlite 均支持),而 convert 是 sql server 特有函数,仅在需用 style 参数精确控制日期/数字格式时才不可替代。

CAST 和 CONVERT 选哪个函数更稳妥
绝大多数场景下,直接用 CAST 更稳妥。它语法统一、跨数据库兼容(PostgreSQL、SQL Server、MySQL 8.0+、SQLite 都认),迁移或换库时不会突然报 Invalid column name 'CONVERT' 这类错误。
CONVERT 是 SQL Server 特有函数,唯一不可替代的点是第三个 style 参数——只在需要精确控制日期/数字字符串格式时才值得用。比如把 '21/05/2024' 转成 DATE,CAST 在 English 语言环境下会失败,而 CONVERT(DATE, '21/05/2024', 103) 明确指定 dd/mm/yyyy 格式就能过。
-
CAST语义清晰:类型写在后面,符合阅读直觉,如CAST(price AS DECIMAL(10,2)) -
CONVERT参数顺序反直觉:CONVERT(VARCHAR, getdate(), 120),且style值(如120)在 PostgreSQL 或 MySQL 中完全无效 - 执行计划层面二者无差异,但
CONVERT容易诱使开发者写出依赖 SQL Server 行为的代码,埋下兼容性隐患
字符串转数字失败时怎么避免报错
直接 CAST('45.6 kg' AS INT) 或 CONVERT(INT, '45.6 kg') 必然报错:Conversion failed when converting the varchar value '45.6 kg' to data type int。它们不自动清理、不截断、不忽略非法字符。
真正能落地的处理方式取决于你用的数据库:
- SQL Server:优先用
TRY_CAST('45.6 kg' AS INT)或TRY_CONVERT(INT, '45.6 kg'),失败返回NULL,不中断查询 - PostgreSQL:没有
TRY_CAST,得先正则清洗:CAST(NULLIF(REGEXP_REPLACE(col, '[^0-9.-]', '', 'g'), '') AS NUMERIC),但要注意负号位置、多个小数点等边界 - MySQL 8.0+:可用
CAST(REPLACE(REPLACE(col, 'kg', ''), ' ', '') AS DECIMAL),但必须前置过滤,否则仍报错;建议加WHERE col REGEXP '^[0-9. ]+$'
日期字符串转 DATE 为什么总出错或变成 1900-01-01
不是函数问题,而是格式和语言环境不匹配。SQL Server 对日期字符串解析极度依赖当前 DATEFORMAT 和 LANGUAGE 设置。比如 CAST('05/21/2024' AS DATE) 在 US 语言下正常,在 British 下就报错;反过来 CAST('21/05/2024' AS DATE) 在 British 下行,US 下崩。
靠改服务器设置不现实,部署一换就失效。可靠做法是显式指定格式:
- ISO 标准格式(推荐):
CONVERT(DATE, '2024-05-21', 120)——120强制按yyyy-mm-dd hh:mi:ss解析,不看语言设置 - 非 ISO 但固定格式:
CONVERT(DATE, '21/05/2024', 103)明确告诉 SQL Server 这是 dd/mm/yyyy - 避免用
CAST解析模糊字符串,除非你 100% 控制输入格式且确认语言环境稳定
长度参数不写会怎样?默认值是多少
CAST 和 CONVERT 对可变长类型(如 VARCHAR、NVARCHAR、CHAR)都支持可选的长度参数,但不写后果不同:
-
CAST(expr AS VARCHAR):SQL Server 默认长度是30,不是1,也不是无限长。如果源数据超 30 字符,会被无声截断 -
CONVERT(VARCHAR, expr):同样默认30,但很多开发者误以为是MAX,结果导出数据被砍掉后半段 - 安全写法:显式写长度,如
CAST(name AS VARCHAR(100))或CONVERT(VARCHAR(255), description);若真要最大长度,用VARCHAR(MAX),不能省略(MAX)
最常被忽略的是:这种截断不报错、不警告,查出来数据“看起来对”,实际业务逻辑可能因字段变短而悄然出错。










