Spark Scala通过JDBC读取MySQL无效日期0000-00-01的解决方案
处理Spark Scala读取MySQL中0000-00-01无效日期的方案
0000-00-01属于MySQL中的无效日期(月份、日期不能为0),zeroDateTimeBehavior=convertToNull仅处理全零的0000-00-00日期,因此需要额外处理这类半零无效日期,以下是几种可行方案:
方案一:在查询SQL中提前过滤/转换无效日期
直接在MySQL查询阶段处理无效日期,避免Spark读取时触发报错。可以用MySQL的条件函数将无效日期转为NULL或合法默认值:
示例1:通用判断无效日期
SELECT id, name, -- 利用STR_TO_DATE判断日期合法性,无效则返回NULL CASE WHEN STR_TO_DATE(your_date_col, '%Y-%m-%d') IS NULL THEN NULL ELSE your_date_col END AS your_date_col FROM your_table
示例2:精准匹配目标无效日期
如果仅需处理0000-00-01这类特定值,可直接匹配替换:
SELECT *, IF(your_date_col = '0000-00-01', NULL, your_date_col) AS cleaned_date FROM your_table
方案二:修改JDBC连接参数+Spark后续处理
通过JDBC参数允许驱动读取无效日期,再在Spark中清洗数据:
1. 修改JDBC URL
添加allowInvalidDates=true参数,让MySQL JDBC驱动跳过日期合法性校验:
val a = "jdbc:mysql://<host_name>:3306/<database_name>?zeroDateTimeBehavior=convertToNull&allowInvalidDates=true"
2. 读取时指定日期列为字符串(可选)
若驱动仍无法解析无效日期为Date类型,可强制将日期列按字符串读取,后续再处理:
val mysqlServerDF = sparkSession.read.format("jdbc") .option("url", a) .option("query", "SELECT * FROM your_table") .option("user", jdbcUserName) .option("password", jdbcPassword) .option("customSchema", "id INT, name STRING, your_date_col STRING") // 自定义schema,将日期列设为字符串 .load()
3. Spark中清洗无效日期
用UDF将无效日期转为NULL或合法值:
import org.apache.spark.sql.functions._ import java.time.LocalDate import java.time.format.DateTimeParseException // 自定义UDF:判断日期字符串是否合法,无效则返回NULL val validateDate = udf((dateStr: String) => { try { LocalDate.parse(dateStr) dateStr } catch { case _: DateTimeParseException => null } }) // 应用UDF清洗日期列 val cleanedDF = mysqlServerDF.withColumn("your_date_col", validateDate(col("your_date_col")))
方案三:自定义JDBC类型转换器(进阶)
若需更底层的日期解析控制,可自定义JDBC类型转换器,重写日期解析逻辑,但该方法复杂度较高,仅推荐有JDBC开发经验的场景使用。
内容的提问来源于stack exchange,提问作者Ajay Makkar
相关产品推荐
相关产品推荐

