SQL中varchar转decimal类型时的报错原因咨询
SQL中varchar转decimal类型时的报错原因咨询
这个坑我之前踩过!核心原因是CASE表达式的隐式类型转换在搞鬼,我给你一步步拆解清楚:
首先看你写的第二个查询:
select distinct cast(case when [fieldname] is null then 0 else [fieldname] end as decimal(20,6)) as [fieldname] from [tablename]
这里then 0返回的是int类型,而else [fieldname]是varchar类型。SQL Server处理CASE表达式时有个规则:所有分支的返回值必须统一成同一个数据类型,这个类型由优先级更高的那个分支决定——int的优先级比varchar高,所以它会先尝试把else分支的所有varchar值转成int,再把整个CASE的结果传给外层的CAST。
而你那个值'85187.003136'是带小数的字符串,转int肯定失败,这就是为什么你看到的错误是“转int失败”,而不是转decimal的问题——因为外层的CAST还没执行,CASE内部就已经触发了隐式转换的错误。
你单独测试cast('85187.003136' as Decimal(20,6))没问题,是因为这里没有中间的隐式转int步骤,直接转decimal当然正常。
解决办法
- 统一CASE分支的返回类型:把then分支的
0改成decimal类型的0.0(或者更明确的0.000000),这样CASE表达式的所有分支都会以decimal/varchar的形式处理,不会触发隐式转int:
select distinct cast(case when [fieldname] is null then 0.0 else [fieldname] end as decimal(20,6)) as [fieldname] from [tablename]
- 更严谨的写法:直接把then分支的0转成目标decimal类型,彻底避免类型歧义:
select distinct cast(case when [fieldname] is null then cast(0 as decimal(20,6)) else [fieldname] end as decimal(20,6)) as [fieldname] from [tablename]
- 排查非法数据:为了保险起见,你可以先找出所有无法正常转成decimal的记录,避免后续还有其他坑:
select [fieldname] from [tablename] where TRY_CAST([fieldname] as decimal(20,6)) is null and [fieldname] is not null
这个查询会返回所有非空但转decimal失败的字段值,比如带字母、特殊符号或者格式异常的字符串,方便你提前清理数据。
这样应该就能解决你的问题了!




