[英]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:您的输入字符串不符合以下两个条件:
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.搜索堆栈溢出,因为它已经被多次覆盖。
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:如果您要跟踪时刻,则必须使用:
TIMESTAMP WITH TIME ZONE
.类型类似于 SQL 标准TIMESTAMP WITH TIME ZONE
数据库列。Instant
, OffsetDateTime
, or ZonedDateTime
(with only OffsetDateTime
required to be supported in JDBC 4.2).这些 Java 类之一: Instant
、 OffsetDateTime
或ZonedDateTime
(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偏移量的上下文。
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
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
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.