如何在Spark 2.4.1中将jdbc / partitionColumn类型设置为Date

时间:2019-05-03 08:27:26

标签: apache-spark apache-spark-sql databricks

我正在尝试使用spark-sql-2.4.1版本从oracle检索数据。 我试图将JdbcOptions设置如下:

    .option("lowerBound", "31-MAR-02");
    .option("upperBound", "01-MAY-19");
    .option("partitionColumn", "data_date");
    .option("numPartitions", 240);

但是给出了错误:

    java.lang.IllegalArgumentException: Timestamp format must be yyyy-mm-dd hh:mm:ss[.fffffffff]
        at java.sql.Timestamp.valueOf(Timestamp.java:204)
        at org.apache.spark.sql.execution.datasources.jdbc.JDBCRelation$.toInternalBoundValue(JDBCRelation.scala:179)

然后尝试如下

    .option("lowerBound", "2002-03-31"); //changed the date format
    .option("upperBound", "2019-05-02");
    .option("partitionColumn", "data_date"); 
    .option("numPartitions", 240);

仍然没有运气。 那么将日期传递为“ lower / upperBound”的正确方法是什么? 有没有一种方法可以指定/设置选项参数数据类型?

第2部分 正确检查了选项。 在执行查询之前,它们之间被覆盖。 因此更正了它。 ...现在该错误已解决。

但是对于以下选项:

.option("lowerBound", "2002-03-31 00:00:00"); 
.option("upperBound", "2019-05-01 23:59:59");
.option("timestampFormat", "yyyy-mm-dd hh:mm:ss");

查询字符串:

query ->  ( SELECT * FROM MODEL_VALS ) T

它抛出另一个错误:

java.sql.SQLException: ORA-12801: error signaled in parallel query server P022, instance nj0005

ORA-01861: literal does not match format string

4 个答案:

答案 0 :(得分:2)

在解决类似问题时,我偶然发现了这个问题。 但是在这种情况下,Spark 2.4.2将以'yyyy-MM-dd HH:mm:ss.ssss'格式发送日期到Oracle,并且返回了“无效月份”,因为它期望的是'dd-MMM-yy HH:mm :ss.ssss'。 为了解决这个问题,我遵循了:Spark GitHub Link ,它说:

  

重写OracleDialect中的beforeFetch方法以完成以下操作   两件事:

     

将Oracle的NLS_TIMESTAMP_FORMAT设置为“ YYYY-MM-DD HH24:MI:SS.FF”以   匹配java.sql.Timestamp格式。将Oracle的NLS_DATE_FORMAT设置为   “ YYYY-MM-DD”以匹配java.sql.Date格式。

它解决了问题。希望对您有所帮助。

答案 1 :(得分:1)

给定的参数具有时间戳记类型,但您仅提供日期。时间戳记的格式为yyyy-mm-dd hh:mm:ss,因此您需要将日期分别设置为2002-03-31 00:00:002019-05-01 23:59:59 ...

答案 2 :(得分:0)

必须以这种方式设置以下所有选项,以使其起作用:

spark.read
      .option("header", true)
      .option("inferSchema", true)
      .option("timestampFormat", "MM/dd/yyyy h:mm:ss a")
      .csv("PATH_TO_CSV")

答案 3 :(得分:0)

如果您使用的是Oracle,请参见https://github.com/apache/spark/blob/master/external/docker-integration-tests/src/test/scala/org/apache/spark/sql/jdbc/OracleIntegrationSuite.scala#L441

val df1 = spark.read.format("jdbc")
      .option("url", jdbcUrl)
      .option("dbtable", "datetimePartitionTest")
      .option("partitionColumn", "d")
      .option("lowerBound", "2018-07-06")
      .option("upperBound", "2018-07-20")
      .option("numPartitions", 3)
      // oracle.jdbc.mapDateToTimestamp defaults to true. If this flag is not disabled, column d
      // (Oracle DATE) will be resolved as Catalyst Timestamp, which will fail bound evaluation of
      // the partition column. E.g. 2018-07-06 cannot be evaluated as Timestamp, and the error
      // message says: Timestamp format must be yyyy-mm-dd hh:mm:ss[.fffffffff].
      .option("oracle.jdbc.mapDateToTimestamp", "false")
      .option("sessionInitStatement", "ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD'")
      .load()