You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Azure Databricks写入Azure SQL时Double值转为指数格式问题

问题描述
  • 通过JDBC将Azure Databricks的Double类型数据写入Azure SQL数据库时,目标字段设为nvarchar/varchar/float类型,写入值会自动转换为指数格式
  • 目标字段设为decimal/numeric类型时不会出现指数格式,但数值末尾会生成多余的0,且由于Databricks表数据未做规范定义,无法提前确认精度值是否能覆盖全量数据存储需求
  • 提前将Databricks中对应列转为String类型再写入字符类型字段,数据仍然会被转换为指数格式

原写入代码如下:

%scala
spark.sql("select ID from customers")
     .write
     .mode(SaveMode.Append) // 追加写入已有表
     .jdbc(jdbcUrl,stg.customers, connectionProperties)

Databricks中ID列示例数据:

ID
1900845009567889.12
2134012183812321

Azure SQL目标字段设为numeric(38,15)时的写入结果:

ID
1900845009567889.1200000000000000
2134012183812321.0000000000000000

解决方案

问题根源是Spark对Double类型的默认字符串序列化、JDBC类型映射逻辑会自动触发科学计数法转换,用以下两步处理即可,不需要提前固定decimal精度,也不会出现多余尾0:

  1. Databricks端写入前做格式化处理:不要直接用原始Double类型、也不要直接用cast(col as string)转字符串(Spark默认Double转String大数值就会出科学计数法,这是之前转String写入仍然失效的核心原因),用格式化函数把数值转成不带科学计数法、自动去除无意义尾0的字符串即可。
    修改后的写入代码:
    %scala
    import org.apache.spark.sql.functions.expr
    
    spark.sql("select ID from customers")
         // 核心转换:先按最高30位小数转成非科学计数法字符串,再用正则去除末尾多余的0和无意义的小数点
         .withColumn("ID", expr("regexp_replace(format_number(ID, 30), '\\.?0+$', '')"))
         .write
         .mode(SaveMode.Append)
         .jdbc(jdbcUrl, "stg.customers", connectionProperties)
    
    这段转换可以自动适配整数、带小数的场景:整数会去掉末尾的.0,带小数的值会只保留有效小数位,和原始展示值完全一致。
  2. Azure SQL端目标字段设置为nvarchar(50)类型:此时JDBC拿到的是已经格式化好的纯数字字符串,不会触发数值类型自动转科学计数法的逻辑,写入结果完全符合预期。
    如果后续需要在SQL中对该字段做数值计算,查询时临时用CAST(ID AS DECIMAL(38,15))转换即可,存储阶段用字符串类型可以完全规避精度丢失、格式异常问题。

内容的提问来源于stack exchange,提问作者Kshitij

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 15:03:11