将 oracle.sql.TIMESTAMPTZ 转换为字符串值的问题
Posted
技术标签:
【中文标题】将 oracle.sql.TIMESTAMPTZ 转换为字符串值的问题【英文标题】:Troubles with converting oracle.sql.TIMESTAMPTZ to string value 【发布时间】:2014-10-24 04:56:19 【问题描述】:我尝试从 oracle db 获取一些数据,将这些数据放入 json 并在其他地方使用,但我在转换 timestamptz 时遇到问题。 Oracle 以字符串格式为我提供带有时区的时间戳,例如“23.10.14 18:34:16,000000 ASIA/NOVOSIBIRSK”。这是我的一些代码。
public void loadFromDb(ResultSet resultSet, Connection oc) throws SQLException
ResultSetMetaData metaData = resultSet.getMetaData();
int columnCount = metaData.getColumnCount();
for (int i = 1; i <= columnCount; i++)
Object obj = resultSet.getObject(i);
if (obj == null)
continue;
if (obj instanceof TIMESTAMPTZ)
TIMESTAMPTZ ts = (TIMESTAMPTZ) obj;
if (oc != null)
super.setValue(metaData.getColumnName(i), ts.stringValue(oc));
else
super.setValue(metaData.getColumnName(i), ts.stringValue());
我得到了这个异常
java.sql.SQLException: Conversion to String failed
at oracle.sql.Datum.stringValue(Datum.java:181)
顺便说一句,早些时候我得到了数字格式的时区,比如“XX:XX”,这段代码也不起作用,但是用这个神奇的super.setValue(metaData.getColumnName(i), ts.stringValue(null))
now 来处理空指针异常。
请帮助我,因为我尝试了 javadocs 中的所有内容。
【问题讨论】:
您的 jdbc 驱动程序可能存在一些问题 + 您读过这个吗? ***.com/questions/17559658/… 我认为解决问题的最简单方法是检索带有时区的时间戳的字符串表示(如果可能的话) @Multisync 也许我误解了你,但这是我的问题 - 获取带有时区的时间戳的字符串表示 我的意思是 select to_char(col_timestamp_with_time_zone, 'format') ... 你需要哪种格式? @Multisync 我不能在数据库端做任何事情。我只是调用返回一些结果集的过程。谢谢你的链接,我认为 #4(write own toString()) 是我的情况的一种可能方式.... 【参考方案1】:TIMESTAMP
不是字符串,反之亦然。您需要使用TO_CHAR
和所需格式将其转换为字符串。
SQL> SELECT SYSTIMESTAMP
2 FROM dual
3 /
SYSTIMESTAMP
---------------------------------------------------------------------------
24-OCT-14 11.14.55.116000 AM +05:30
SQL>
SQL> SELECT TO_CHAR(systimestamp, 'DD-MON-YYYY HH24:MI:SS.FF TZH:TZM') tm
2 FROM dual
3 /
TM
-------------------------------------
24-OCT-2014 11:14:55.163000 +05:30
SQL> SELECT to_timestamp_tz('24-OCT-2014 11:07:40.348000 +05:30','DD-MON-YYYY HH24:MI:SS.FF TZH:TZM') tm
2 FROM dual
3 /
TM
---------------------------------------------------------------------------
24-OCT-14 11.07.40.348000000 AM +05:30
SQL> SELECT TO_TIMESTAMP('24-OCT-2014', 'DD-MON-YYYY')
2 FROM dual
3 /
TO_TIMESTAMP('24-OCT-2014','DD-MON-YYYY')
---------------------------------------------------------------------------
24-OCT-14 12.00.00.000000000 AM
让我们验证一下。
SQL> set serveroutput on;
SQL> DECLARE
2 tm_stamp TIMESTAMP;
3 tm_string VARCHAR2(30);
4 BEGIN
5 SELECT SYSTIMESTAMP INTO tm_stamp FROM dual;
6 dbms_output.put_line(tm_stamp);
7 SELECT SYSTIMESTAMP INTO tm_string FROM dual;
8 dbms_output.put_line(tm_string);
9 END;
10 /
24-OCT-14 11.17.35.180000 AM
DECLARE
*
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error
ORA-06512: at line 7
SQL>
所以,tm_string 不能存储时间戳,因为 tm_stamp 是字符串类型而不是时间戳。
正确的方法是显式转换成字符串。
SQL> DECLARE
2 tm_stamp TIMESTAMP;
3 tm_string VARCHAR2(50);
4 BEGIN
5 SELECT TO_CHAR(systimestamp, 'DD-MON-YYYY HH24:MI:SS.FF TZH:TZM') INTO tm_string FROM dual;
6 dbms_output.put_line(tm_string);
7 END;
8 /
24-OCT-2014 11:25:20.060000 +05:30
PL/SQL procedure successfully completed.
SQL>
【讨论】:
谢谢,但我的 java 资源有限,因为我无法在 db 端做任何事情。我只是调用返回一些结果集的过程。【参考方案2】:TIMESTAMPTZ
的格式为well documented。我们目前使用the following code。
如果您使用的是 Java SE 8 和 ojdbc8,则可以使用 getObject(int, OffsetDateTime.class)
。如果你使用getObject(int, ZonedDateTime.class)
,你可能会受到bug 25792016的影响。
【讨论】:
以上是关于将 oracle.sql.TIMESTAMPTZ 转换为字符串值的问题的主要内容,如果未能解决你的问题,请参考以下文章
Javascript 将正则表达式 \\n 替换为 \n,将 \\t 替换为 \t,将 \\r 替换为 \r 等等