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

PySpark读取Oracle NUMBER类型精度超限问题(无需显式Schema)

解决PySpark读取Oracle NUMBER字段精度超限问题

问题背景

使用PySpark通过JDBC读取Oracle表时,表中包含35位长度的NUMBER类型字段,Spark自动推断Schema时将其识别为decimal(38,10),执行show()时抛出java.lang.ArithmeticException: Decimal precision 45 exceeds max precision 38错误,且不想通过显式定义Schema解决。

可行解决方案

1. 允许Decimal精度损失

通过Spark配置项spark.sql.decimalOperations.allowPrecisionLoss开启精度损失允许,让Spark自动处理超过38位精度的decimal值,避免报错。

from pyspark.sql import SparkSession

spark = SparkSession.builder \
    .appName("OracleDecimalFix") \
    .config("spark.sql.decimalOperations.allowPrecisionLoss", "true") \
    .getOrCreate()

# 后续读取逻辑不变
df_rdbms_data = spark.read.jdbc(url=source_jdbc_url, table=source_table_name, properties=source_properties)
df_rdbms_data.printSchema()
df_rdbms_data.show()

该方案适合可以接受轻微精度损失的场景,Spark会自动截断超出精度范围的部分。

2. 将NUMBER字段转为字符串读取

通过JDBC自定义查询,把Oracle的NUMBER字段转换为字符串类型读取,从根源避免decimal精度问题。

# 构造包含字段转换的查询语句,替换other_columns为表中其他字段
query = f"(SELECT CAST(add_digit_num AS VARCHAR2(40)) AS add_digit_num, other_columns FROM {source_table_name}) AS temp_table"

df_rdbms_data = spark.read.jdbc(url=source_jdbc_url, table=query, properties=source_properties)
df_rdbms_data.printSchema()  # 此时add_digit_num为string类型
df_rdbms_data.show()

若后续需要数值运算,可在Spark中再将字符串转换为精度符合要求的decimal类型(确保实际值精度≤38)。

3. 调整Oracle JDBC映射规则

修改JDBC连接属性,禁止将Oracle NUMBER映射为BigDecimal,转而使用基础数值类型(注意:超大数值可能出现精度损失,需根据实际数据评估)。

source_properties = {
    "user": "your_username",
    "password": "your_password",
    "driver": "oracle.jdbc.driver.OracleDriver",
    "oracle.jdbc.mapNumberToBigDecimal": "false"
}

df_rdbms_data = spark.read.jdbc(url=source_jdbc_url, table=source_table_name, properties=source_properties)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 21:33:26