简体   繁体   English

Oracle - 如何在不格式化的情况下将 Java 项目中的时间戳作为字符串插入

[英]Oracle - How can i insert timestamp from Java Project as String without formatting

in a spring projekt there is a sql data which insert values to a oracle database.在 spring 项目中,有一个 sql 数据将值插入到 oracle 数据库中。 if i try to insert a timestamp i get a ORA-Exception (not a valid month).如果我尝试插入时间戳,我会收到 ORA-Exception(无效月份)。

INSERT INTO TAB (colTimestamp)
VALUES ('2020-05-07-10.05.05.301011')

Why is that not a valid month ?为什么那不是一个有效月份?

There is no problem in DB2.在 DB2 中没有问题。 So in which format should i insert a timestamp ?那么我应该以哪种格式插入时间戳? i also tried 2019-05-05 10:10:10 but i get the same exception How can i insert a timestamp ?我也试过2019-05-05 10:10:10但我得到了同样的异常 如何插入时间戳? What is the default format of timestamp in oracle ? oracle 中时间戳的默认格式是什么?

You need to use a proper timestamp literal formatted using the ISO format:您需要使用使用 ISO 格式格式化的正确时间戳文字:

timestamp '2020-05-07 10:05:05.301011'

So no - between the date and the time, and : to separate hour, minutes and seconds.所以没有-在日期和时间之间,和:分隔小时、分钟和秒。 I believe the same would work in DB2 as well.我相信同样适用于 DB2。

If your are doing the insert through JDBC, you should not pass a String to begin with.如果您通过 JDBC 进行插入,则不应以字符串开头。 Use a PreparedStatement and pass an instance of java.time.LocalDateTime or at least java.sql.Timestamp使用PreparedStatement并传递java.time.LocalDateTime或至少java.sql.Timestamp的实例

The Answer by a_horse_with_no_name is correct. a_horse_with_no_name答案是正确的。 Here's a bit more detail and example.这里有更多的细节和例子。

Your input string fails to comply with both:您的输入字符串不符合以下两个条件:

  • SQL format: YYYY-MM-DD HH:MM:SS SQL 格式:YYYY-MM-DD HH:MM:SS
  • ISO 8601 format: YYYY-MM-DDTHH:MM:SS (with a T separating date from time) ISO 8601格式:YYYY-MM-DDTHH:MM:SS(用T分隔日期和时间)

In contrast, your input string has a hyphen in the middle, and fails to use colon characters for delimiting hours-minutes-seconds.相比之下,您的输入字符串中间有一个连字符,并且无法使用冒号字符来分隔小时-分钟-秒。

The ISO 8601 formats are used by default when the java.time are parsing or generating strings.java.time解析或生成字符串时,默认使用 ISO 8601 格式。

String input = "2020-05-07T10:05:05.301011" ;
LocalDateTime ldt = LocalDateTime.parse( input ) ;

For working in Java, you should be passing objects as values for the placeholders in a prepared statement rather than as text within a String object.对于在 Java 中工作,您应该在准备好的语句中将对象作为占位符的值而不是作为String对象中的文本传递。

String sql = "INSERT INTO some_table ( some_timestamp ) VALUES ( ? ) ;" ;
myPreparedStatement.setObject( 1 , ldt ) ;

If you insist on using straight text rather than objects, use SQL formatting for the date-time input.如果您坚持使用纯文本而不是对象,请对日期时间输入使用 SQL 格式。 I would simply take the ISO 8601 output generated by default in java.time and replace the T with a SPACE.我会简单地采用java.time 中默认生成的 ISO 8601 输出并将T替换为空格。

String sql = String sql = "INSERT INTO some_table ( some_timestamp ) VALUES ( " + ldt.toString().replace( "T" , " " ) + " ) ;" ;

Alternatively, you could generate that text by using a DateTimeFormatter object.或者,您可以使用DateTimeFormatter对象生成该文本。 Search Stack Overflow as that has been covered many many times already.搜索堆栈溢出,因为它已经被多次覆盖。

Moment片刻

You have another crucial problem in your code.您的代码中还有另一个关键问题。 Your use of the word "timestamp" suggest you are trying to track a moment, a specific point on the timeline.您对“时间戳”一词的使用表明您正在尝试跟踪某个时刻,即时间轴上的特定点。 Your input string fails to do that.您的输入字符串无法做到这一点。 Your input lacks the context of an offset-from-UTC (a number of hours-minutes-second ahead/behind the prime meridian) or a time zone (a name in Continent/Region format ).您的输入缺少UTC 偏移量(本初子午线之前/之后的时分秒数)或时区Continent/Region格式名称)的上下文。

Take for example your input of 10 AM.以您输入的 10 AM 为例。 We have no way to know if you meant 10 AM in Tokyo Japan or 10 AM in Toledo Ohio US, two very different moments many hours apart.我们无法知道您是指日本东京的上午 10 点还是美国俄亥俄州托莱多的上午 10 点,这两个非常不同的时刻相隔许多小时。

If you are tracking moments, you must use:如果您要跟踪时刻,则必须使用:

  • A database column of a type akin to the SQL standard TIMESTAMP WITH TIME ZONE .类型类似于 SQL 标准TIMESTAMP WITH TIME ZONE数据库列。
  • One of these Java classes: Instant , OffsetDateTime , or ZonedDateTime (with only OffsetDateTime required to be supported in JDBC 4.2).这些 Java 类之一: InstantOffsetDateTimeZonedDateTime (JDBC 4.2 中只需要支持OffsetDateTime )。

Example:例子:

OffsetDateTime now = OffsetDateTime.now( ZoneOffset.UTC ) ;  // Capture the current moment in UTC. 

To represent a moment as text, you should use ISO 8601 format ending in either Z (for UTC, an offset of zero), an offset such as +05:30 , or an offset followed by the name of a time zone in square brackets.要将时刻表示为文本,您应该使用 ISO 8601 格式以Z (对于 UTC,偏移量为零)、偏移量(例如+05:30 )或偏移量后跟方括号中的时区名称. That last one is a non-standard extension to ISO 8601 used by the java.time.ZonedDateTime class.最后一个是java.time.ZonedDateTime类使用的 ISO 8601 的非标准扩展。

Instant instant = Instant.parse( "2020-05-07T10:05:05.301011Z" ) ;

JDBC 4.2 requires support for OffsetDateTime but not Instant . JDBC 4.2 需要支持OffsetDateTime而不是Instant Your JDBC driver may support Instant , but if not, convert.您的 JDBC 驱动程序可能支持Instant ,但如果不支持,请转换。

OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;

When tracking moments, never use a database type akin to the SQL standard type TIMESTAMP WITHOUT TIME ZONE .跟踪时刻时,切勿使用类似于 SQL 标准类型TIMESTAMP WITHOUT TIME ZONE的数据库类型。 And never use the Java class LocalDateTime for moments.并且永远不要使用 Java 类LocalDateTime片刻。 Both intentionally lack the context of a time zone or offset-from-UTC.两者都故意缺少时区或UTC偏移量的上下文。

Java(旧版和现代版)和标准 SQL 中的日期时间类型表

Kindly follow the ISO date formats so that Oracle will accept it as a date.请遵循 ISO 日期格式,以便 Oracle 接受它作为日期。

Eg1:例1:

INSERT INTO TAB (colTimestamp)
VALUES ('2020-05-07 10:05:05.301011')

Eg2:例2:

INSERT INTO TAB (colTimestamp)
VALUES ('2020-05-07T10:05:05.301011')

Syntax is - YYYY-MM-DD hh:mi:ss.SS语法是 - YYYY-MM-DD hh:mi:ss.SS

The formatting of a LocalDateTime, at least as taken by a Java DateFormatter, would be: LocalDateTime 的格式,至少由 Java DateFormatter 所采用,将是:


    private static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("YYYY-MM-dd hh:mm:ss.SS");
    LocalDateTime localDateTime = LocalDateTime.of(2021, 12, 31, 14, 30, 15, 300);
    System.out.println(formatter.format(localDateTime));

Which would give:这会给:

2022-12-31 02:30:15.00 2022-12-31 02:30:15.00

java.time时间

The following table depicts the mapping of ANSI SQL types with java.time types: 下表描述了 ANSI SQL 类型与java.time类型的映射:

ANSI SQL ANSI SQL Java SE 8 Java SE 8
DATE日期 LocalDate本地日期
TIME时间 LocalTime当地时间
TIMESTAMP时间戳 LocalDateTime本地日期时间
TIME WITH TIMEZONE时区时间 OffsetTime偏移时间
TIMESTAMP WITH TIMEZONE带时区的时间戳 OffsetDateTime偏移日期时间

Assuming that your database column is of type, TIMESTAMP , you can parse the given Date-Time string into LocalDateTime as shown below:假设您的数据库列的类型为TIMESTAMP ,您可以将给定的日期时间字符串解析为LocalDateTime ,如下所示:

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        String strDateTime = "2020-05-07-10.05.05.301011";
        
        DateTimeFormatter dtf = new DateTimeFormatterBuilder()
                                .append(DateTimeFormatter.ISO_LOCAL_DATE)
                                .appendLiteral("-")
                                .appendPattern("HH.mm.ss")
                                .appendFraction(ChronoField.NANO_OF_SECOND, 0, 9, true)
                                .toFormatter(Locale.ENGLISH);
        
        LocalDateTime ldt = LocalDateTime.parse(strDateTime, dtf);
        System.out.println(ldt);
    }
}

Output:输出:

2020-05-07T10:05:05.301011

ONLINE DEMO在线演示

Now, you can store this LocalDateTime into the database as shown below:现在,您可以将此LocalDateTime存储到数据库中,如下所示:

PreparedStatement st = conn.prepareStatement("INSERT INTO mytable (columnfoo) VALUES (?)");
st.setObject(1, ldt);
st.executeUpdate();
st.close();

Given below is a sample code to retrieve a LocalDate from columnfoo:下面给出了从 columnfoo 检索 LocalDate 的示例代码:

Statement st = conn.createStatement();
ResultSet rs = st.executeQuery("SELECT * FROM mytable WHERE <some condition>");
while (rs.next()) {
    // Assuming the column index of columnfoo is 1
    LocalDateTime ldt = rs.getObject(1, LocalDateTime.class));
    System.out.println(ldt);
}
rs.close();
st.close();

Learn more about the modern Date-Time API * from Trail: Date Time .Trail: Date Time 中了解有关现代日期时间 API * 的更多信息。


* If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring . * 如果您正在为 Android 项目工作并且您的 Android API 级别仍然不符合 Java-8,请检查 通过 desugaring 可用的 Java 8+ API Note that Android 8.0 Oreo already provides support for java.time .请注意,Android 8.0 Oreo 已提供java.time支持

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 将String转换为TIMESTAMP,以便从servlet java插入到数据库oracle中 - Convert String into TIMESTAMP for insert into Database oracle from servlet java 从Java插入时间戳Oracle列 - insert into timestamp oracle column from java 如何在不剥离格式设置的情况下将HTML转换为字符串? - How can I Convert Html to a String without stripping formatting settings? 我正在从Java读取文本文件以插入到Oracle DB表中,如何跳过前2行? - I am reading the text file from java to insert into oracle DB table, how can skip first 2 lines? 从 Java 到 Oracle 插入数千条记录,如何才能获得最佳性能? - Insert thousands of records from Java to Oracle, how can I get the best performance? 如何使用Java防止oracle数据库中的重复插入? - How can I prevent duplicated insert in oracle database with Java? Java反思:如何在不将另一个项目或JAR添加到我的类路径的情况下从另一个项目加载一个类? - Java reflection: How can I load a class from another project without adding that project or JAR to my classpath? 如何在Java中编写时间戳,以便可以在mysql中插入 - How can I write a Timestamp in java so I can insert in mysql Java - Oracle - DB Insert - Timestamp to Date 列 - Java - Oracle - DB Insert - Timestamp to Date column 从Java时间戳转换为Oracle时间戳 - Converting from Java Timestamp to Oracle Timestamp
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM