这里对使用sqoop将Oracle中的数据按照日期、小时批量导入数据报错与解决做一个总结。
之前mysql导入数据过,那时候对于 --query 后的sql语句因为涉及到日期与时间,如果是单引号的话则会跟外面的单引号冲突,导致错误,所以mysql中解决办法就是里面涉及日期与时间的字段改成双引号即可。然后再弄Oracle时候,我也试着改成双引号,并且因为sqoop导入时候用到了where判断,所以需要添加了 $CONDITIONS 条件:
sqoop import --connect jdbc:oracle:thin:@192.168.99.19:1521:jcxydb --username sjbzk --password sjbzk --driver oracle.jdbc.driver.OracleDriver --query 'select * from GXTS_MJSKXX where to_date(SKSJ,"yyyy-mm-dd HH24:mi:ss")>to_date(to_char(sysdate-1/24,"yyyy-mm-dd HH24"),"yyyy-mm-dd HH24:mi:ss") and to_date(SKSJ,"yyyy-mm-dd HH24:mi:ss")<to_date(to_char(sysdate,"yyyy-mm-dd HH24"),"yyyy-mm-dd HH24:mi:ss") and $CONDITIONS' --target-dir /user/jcxydb/GXTS_MJSKXX/$date_today/$hour --fields-terminated-by '\t' --lines-terminated-by '\n' --null-string '\\N' --null-non-string '\\N' --m 1;
结果报错了,报错信息:
20/04/09 14:07:05 INFO manager.SqlManager: Executing SQL statement: select * from GXTS_MJSKXX where to_date(SKSJ,"yyyy-mm-dd HH24:mi:ss")>to_date(to_char(sysdate-1/24,"yyyy-mm-dd HH24"),"yyyy-mm-dd HH24:mi:ss") and to_date(SKSJ,"yyyy-mm-dd HH24:mi:ss")<to_date(to_char(sysdate,"yyyy-mm-dd HH24"),"yyyy-mm-dd HH24:mi:ss") and (1 = 0)
20/04/09 14:07:05 ERROR manager.SqlManager: Error executing statement: java.sql.SQLException: ORA-00904: "yyyy-mm-dd HH24:mi:ss": invalid identifier
java.sql.SQLException: ORA-00904: "yyyy-mm-dd HH24:mi:ss": invalid identifier
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:113)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:331)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:288)
at oracle.jdbc.driver.T4C8Oall.receive(T4C8Oall.java:754)
at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:219)
at oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:813)
at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:1051)
at oracle.jdbc.driver.T4CPreparedStatement.executeMaybeDescribe(T4CPreparedStatement.java:854)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1156)
at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3415)
at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3460)
at org.apache.sqoop.manager.SqlManager.execute(SqlManager.java:776)
at org.apache.sqoop.manager.SqlManager.execute(SqlManager.java:785)
at org.apache.sqoop.manager.SqlManager.getColumnInfoForRawQuery(SqlManager.java:288)
at org.apache.sqoop.manager.SqlManager.getColumnTypesForRawQuery(SqlManager.java:259)
at org.apache.sqoop.manager.SqlManager.getColumnTypesForQuery(SqlManager.java:252).....
这里报了 ORA-00904: "yyyy-mm-dd HH24:mi:ss": invalid identifier 错误。
因为Oracle中需要使用单引号,我之前测试用的是单引号,但是因为之前写mysql时候单引号会报错,所以我就改成了双引号。如果双引号直接复制到Oracle中测试也会报00904这个错误。
这就遇到一个问题了,如果就使用单引号呢,外面那个单引号就会报别的错误。如下:
然后我就自己开始瞎鼓捣:
A.比如单引号前面加个反引号.
B.在单引号前面加个单引号
当然这些都是不可以的。。。大家也不要这样尝试了。
然后想了想还是要里面to_date这些一定要用单引号,那么只能外面的–query的单引号改了,然后我讲外面改成双引号,则报了下面的这个错误:
这个错误跟我之前第一次使用不加$CONDITIONS一样的错,可是我这里明明写了的??
后面看了一篇博客,还有就是查了好几个资料,使用sqoop中的-query要注意的坑:
“–query“:如果这里SQL语句里边用过单引号了,那外边必须要用双引号;
- 这里的SQL假如直接使用 “FROM STORE“的话,是会报 table 找不见,或者不存在的,因为使用“–query“的话没有指定 Schema ,所以这里必须使用 . 的形式。
- where 后边必须有 $CONDITIONS 条件,sqoop 运行的时候,看日志发现sqoop 会在这里插入(1=0)或(1=1)来控制这条语句的执行。外边使用双引号的话,$CONDITIONS 前边需要加反斜杠 即:\$CONDITIONS。 Free form query in Sqoop Import with WHERE clause。
终于懂了需要在$CONDITIONS前面加上 "\",然后测试果然成功了。最后成功的代码如下:
sqoop import --connect jdbc:oracle:thin:@192.168.99.19:1521:jcxydb --username sjbzk --password sjbzk --driver oracle.jdbc.driver.OracleDriver --query "SELECT * FROM GXTS_MJSKXX WHERE TO_DATE(SKSJ,'yyyy-mm-dd HH24:mi:ss')>TO_DATE(TO_DATE(sysdate-1/24,'yyyy-mm-dd HH24'),'yyyy-mm-dd HH24:mi:ss') AND TO_DATE(SKSJ,'yyyy-mm-dd HH24:mi:ss')<TO_DATE(TO_DATE(sysdate,'yyyy-mm-dd HH24'),'yyyy-mm-dd HH24:mi:ss') AND \$CONDITIONS" --target-dir /user/jcxydb/GXTS_MJSKXX/$date_today/$hour --fields-terminated-by '\t' --lines-terminated-by '\n' --null-string '\\N' --null-non-string '\\N' --m 1;