try_cast 是 sql server 2012+ 的容错类型转换函数,转换失败返回 null 而非报错,但需显式指定完整类型(如 decimal(10,2)、varchar(50)),且在 where 中使用会导致索引失效,需配合模式匹配预过滤,并注意处理 null 及数值范围。

TRY_CAST 转数字失败时返回 NULL,不是报错
直接用 CAST 或 CONVERT 转字符串为数字,只要遇到 'N/A'、'--'、'$123'、空字符串或带逗号的 '1,000',就会中断整个查询,抛出 Conversion failed when converting the varchar value '...' to data type int.。而 TRY_CAST 是 SQL Server 2012+ 的容错函数:它不抛异常,转换失败就安静返回 NULL。
这适合清洗日志表、导入表或用户输入字段——你不需要先查一遍再过滤,一条语句就能把“能转的转出来,不能转的标为空”。
-
TRY_CAST('123' AS INT)→123 -
TRY_CAST('123.45' AS INT)→NULL(小数点对整型无效) -
TRY_CAST(' 42 ' AS INT)→42(自动 trim 空格) -
TRY_CAST('42'+CHAR(9) AS INT)→NULL(制表符不会被 trim,得提前REPLACE(col, CHAR(9), '')) -
TRY_CAST('' AS INT)→NULL(空字符串也不行)
必须显式指定完整类型,漏写长度会报错
TRY_CAST 不像 CAST 那样对 VARCHAR 或 DECIMAL 有隐式默认长度。漏写精度/长度,SQL Server 直接编译失败,不是运行时返回 NULL。
常见错误写法:
-
TRY_CAST('123.45' AS DECIMAL)→ 报错:缺少精度和小数位数 -
TRY_CAST('hello' AS VARCHAR)→ 报错:VARCHAR必须带长度,如VARCHAR(50)
正确写法:
TRY_CAST('123.45' AS DECIMAL(10,2))TRY_CAST('hello' AS VARCHAR(50))-
TRY_CAST('2024-01-01' AS DATE)✅(DATE是固定长度类型,无需括号)
WHERE 条件里慎用 TRY_CAST,否则索引失效
在 WHERE 子句中写 WHERE TRY_CAST(order_no AS INT) > 1000,哪怕 order_no 字段上有索引,SQL Server 也无法下推索引查找,强制全表扫描——因为 TRY_CAST 是标量函数,优化器无法预估其输出分布。
更可行的做法是分两步过滤:
- 先用模式匹配粗筛:
WHERE order_no NOT LIKE '%[^0-9]%' AND order_no != ''(排除含字母、符号的值) - 再加安全校验:
AND TRY_CAST(order_no AS INT) IS NOT NULL
如果字段长期存数字,建议建计算列或检查约束,而不是每次查询都调用 TRY_CAST。
别忘了处理 NULL,否则后续逻辑可能崩
TRY_CAST 返回 NULL 是设计行为,不是 bug。但如果你把它直接塞进 SUM()、+ 运算或非空列插入,结果可能不符合预期,甚至触发新错误。
推荐组合用法:
- 填默认值:
ISNULL(TRY_CAST(value_col AS INT), 0) - 标记失败行:
CASE WHEN TRY_CAST(value_col AS DECIMAL(10,2)) IS NULL THEN 'invalid' ELSE 'ok' END - 赋值给变量时,必须显式判断:
IF TRY_CAST(@input AS INT) IS NOT NULL SET @num = TRY_CAST(@input AS INT)(不能直接SET @num = TRY_CAST(...),否则编译期可能报“不能将 null 赋给非空变量”)
真正容易被忽略的是:转换后值的精度是否匹配目标列。比如 TRY_CAST('2147483648' AS INT) 返回 NULL(超 INT 上限),但 TRY_CAST('2147483648' AS BIGINT) 就成功;同理,NUMERIC(3,0) 放不下 1234,得同步校验范围或换更大类型。











