0

in a spring projekt there is a sql data which insert values to a oracle database. if i try to insert a timestamp i get a ORA-Exception (not a valid month).

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. 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 ? What is the default format of timestamp in oracle ?

5 Answers 5

4

You need to use a proper timestamp literal formatted using the ISO format:

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.

If your are doing the insert through JDBC, you should not pass a String to begin with. Use a PreparedStatement and pass an instance of java.time.LocalDateTime or at least java.sql.Timestamp

Sign up to request clarification or add additional context in comments.

Comments

2

The Answer by a_horse_with_no_name is correct. Here's a bit more detail and example.

Your input string fails to comply with both:

  • SQL format: YYYY-MM-DD HH:MM:SS
  • ISO 8601 format: YYYY-MM-DDTHH:MM:SS (with a T separating date from time)

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.

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.

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. I would simply take the ISO 8601 output generated by default in java.time and replace the T with a SPACE.

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. 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).

Take for example your input of 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.

If you are tracking moments, you must use:

  • A database column of a type akin to the SQL standard TIMESTAMP WITH TIME ZONE.
  • One of these Java classes: Instant, OffsetDateTime, or ZonedDateTime (with only OffsetDateTime required to be supported in JDBC 4.2).

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. That last one is a non-standard extension to ISO 8601 used by the java.time.ZonedDateTime class.

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

JDBC 4.2 requires support for OffsetDateTime but not Instant. Your JDBC driver may support Instant, but if not, convert.

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

When tracking moments, never use a database type akin to the SQL standard type TIMESTAMP WITHOUT TIME ZONE. And never use the Java class LocalDateTime for moments. Both intentionally lack the context of a time zone or offset-from-UTC.

Table of date-time types in Java (both legacy and modern) and in standard SQL

Comments

0

Kindly follow the ISO date formats so that Oracle will accept it as a date.

Eg1:

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

Eg2:

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

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

Comments

0

The formatting of a LocalDateTime, at least as taken by a Java DateFormatter, would be:


    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

Comments

0

java.time

The following table depicts the mapping of ANSI SQL types with java.time types:

ANSI SQL 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:

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:

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:

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.


* 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. Note that Android 8.0 Oreo already provides support for java.time.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.