Spark导入Excel到全varchar字段SQL Server报float错如何用Java解决
错误根因
即使SQL Server表所有字段都是varchar类型,报错触发的核心原因是Spark读取Excel时默认开启了自动类型推断,部分看起来像数值的列会被推断为float/double类型,JDBC写入时驱动会按数值类型向SQL Server传递参数,当数值存在精度溢出、科学计数法、空值格式异常时就会触发TDS协议的类型校验错误。
解决步骤(Java代码实现)
前置依赖
首先确保你的项目引入了对应Spark版本的Excel读取依赖,以Spark 3.0+、Scala 2.12版本为例:
<dependency> <groupId>com.crealytics</groupId> <artifactId>spark-excel_2.12</artifactId> <version>3.3.1_0.18.7</version> </dependency>
完整代码实现
import org.apache.spark.sql.Dataset; import org.apache.spark.sql.Row; import org.apache.spark.sql.SparkSession; import org.apache.spark.sql.functions; import org.apache.spark.sql.types.DataTypes; import org.apache.spark.sql.types.StructField; import org.apache.spark.sql.types.StructType; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; public class ExcelToSqlServer { public static void main(String[] args) { // 初始化SparkSession SparkSession spark = SparkSession.builder() .appName("ExcelToSqlServerImport") .master("local[*]") // 集群运行时删除该行 .getOrCreate(); // 1. 定义全字段为String类型的Schema,列顺序、列名必须和Excel、SQL Server表完全对齐 StructType excelSchema = DataTypes.createStructType(new StructField[]{ DataTypes.createStructField("id", DataTypes.StringType, true), DataTypes.createStructField("name", DataTypes.StringType, true), DataTypes.createStructField("phone", DataTypes.StringType, true), DataTypes.createStructField("amount", DataTypes.StringType, true), // 按实际列数依次补全所有字段 }); // 2. 读取Excel文件,关闭自动类型推断,强制使用指定Schema Dataset<Row> rawDf = spark.read() .format("com.crealytics.spark.excel") .option("header", "true") // Excel第一行为表头时设为true,否则设为false .option("inferSchema", "false") .schema(excelSchema) .load("file:///你的Excel文件本地路径/或者HDFS路径"); // 二次强制转换所有列为String类型,避免隐式类型转换 List<Column> allStringColumns = Arrays.stream(rawDf.columns()) .map(col -> functions.col(col).cast(DataTypes.StringType)) .collect(Collectors.toList()); Dataset<Row> stringDf = rawDf.select(allStringColumns.toArray(new Column[0])); // 3. 写入SQL Server stringDf.write() .format("jdbc") .option("url", "jdbc:sqlserver://192.168.0.xxx:1433;databaseName=你的库名;sendStringParametersAsUnicode=true") .option("dbtable", "你的表名") .option("user", "数据库用户名") .option("password", "数据库密码") .option("driver", "com.microsoft.sqlserver.jdbc.SQLServerDriver") // 可选:指定写入时的字段类型映射,和SQL Server表字段类型保持一致 .option("customSchema", "id VARCHAR(32),name VARCHAR(64),phone VARCHAR(16),amount VARCHAR(32)") .mode("append") // 覆盖写用overwrite .save(); spark.stop(); } }
注意事项
- Excel列顺序、SQL Server表列顺序、自定义Schema的列顺序必须完全一致,避免列错位导致类型异常
- 如果Excel中存在超长字符串,需要确保SQL Server对应varchar字段的长度足够,避免截断错误
- 批量写入时可以额外添加
.option("batchsize", "1000")参数调整批次大小,优化写入性能
内容的提问来源于stack exchange,提问作者Dhruv Rank
相关产品推荐
相关产品推荐

