PySpark读取Oracle NUMBER类型数据时保留整数格式的问题
解决PySpark读取Oracle NUMBER列时保留整数格式的问题
你的问题是Oracle表中NUMBER(38,10)和NUMBER(9)列实际存储的是整数,但PySpark通过JDBC读取后显示带 trailing zeros(比如100522.0000000000),想要输出纯整数格式,这里有几种实用方案:
方案1:在读取SQL中直接转换类型
修改dbtable里的查询语句,用CAST把列转成无小数位的数值类型,让Spark读进来就是整数类型:
source_df = self.spark.read.format("jdbc")\ .option("url", self.Oracle_jdbc_url)\ .option("dbtable", "(select CAST(C1 AS NUMBER(38)) C1, CAST(C2 AS NUMBER(9)) C2 from schema.table where rownum <=2 ) ")\ .option("user", self.Oracle_Username)\ .option("password", self.Oracle_Password)\ .option("numPartitions",2)\ .option("lowerBound", 1)\ .option("upperBound",100000)\ .option("partitionColumn", "c1")\ .load() source_df.show()
这种方式从数据源层面修正类型,后续处理无需再调整。
方案2:读取后转换列类型
如果不想修改查询SQL,读入DataFrame后再把列转成整数类型。注意NUMBER(38,10)的范围可能超过IntegerType上限,建议用LongType或BigInt避免溢出:
from pyspark.sql.types import LongType, IntegerType source_df = self.spark.read.format("jdbc")\ .option("url", self.Oracle_jdbc_url)\ .option("dbtable", "(select C1,C2 from schema.table where rownum <=2 ) ")\ .option("user", self.Oracle_Username)\ .option("password", self.Oracle_Password)\ .option("numPartitions",2)\ .option("lowerBound", 1)\ .option("upperBound",100000)\ .option("partitionColumn", "c1")\ .load() # 转换列类型 source_df = source_df\ .withColumn("C1", source_df["C1"].cast(LongType()))\ .withColumn("C2", source_df["C2"].cast(IntegerType())) source_df.show()
方案3:指定自定义Schema读取
通过customSchema选项直接告诉JDBC要读取的列类型,跳过默认的类型映射:
source_df = self.spark.read.format("jdbc")\ .option("url", self.Oracle_jdbc_url)\ .option("dbtable", "(select C1,C2 from schema.table where rownum <=2 ) ")\ .option("user", self.Oracle_Username)\ .option("password", self.Oracle_Password)\ .option("numPartitions",2)\ .option("lowerBound", 1)\ .option("upperBound",100000)\ .option("partitionColumn", "c1")\ .option("customSchema", "C1 BIGINT, C2 INT")\ .load() source_df.show()
这个方案适合提前明确列类型和范围的场景,配置一次就能直接得到目标类型的DataFrame。
内容的提问来源于stack exchange,提问作者pbh
相关产品推荐
相关产品推荐

