Oracle - Как я могу вставить метку времени из Java Project в виде строки без форматирования - PullRequest
0 голосов
/ 22 декабря 2019

в весеннем проекте есть данные sql, которые вставляют значения в базу данных oracle. если я пытаюсь вставить метку времени, я получаю исключение ORA (недействительный месяц).

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

Почему этот месяц недействителен?

В DB2 нет проблем. Так в каком формате я должен вставить метку времени? Я также пытался 2019-05-05 10: 10: 10 , но получаю то же исключение. Как я могу вставить метку времени? Каков формат отметки времени по умолчанию в Oracle?

Ответы [ 3 ]

4 голосов
/ 22 декабря 2019

Вам необходимо использовать правильный литерал метки времени, отформатированный с использованием формата ISO:

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

Таким образом, нет - между датой и временем и : для разделения часов, минут и секунд. Я считаю, что то же самое будет работать и в DB2.

Если вы выполняете вставку через JDBC, вам не следует передавать строку для начала. Используйте PreparedStatement и передайте экземпляр java.time.LocalDateTime или хотя бы java.sql.Timestamp

2 голосов
/ 23 декабря 2019

Ответ a_horse_with_no_name правильный. Вот немного подробнее и пример.

Ваша входная строка не соответствует обоим:

  • Формат SQL: ГГГГ-ММ-ДД ЧЧ: ММ: СС
  • ISO 8601 формат: ГГГГ-ММ-ДДЧЧ: ММ: СС (с T, отделяющим дату от времени)

Напротив, в вашей входной строке есть дефис вв середине и не использует двоеточия для разграничения часов-минут-секунд.

Форматы ISO 8601 используются по умолчанию, когда java.time выполняет синтаксический анализ или генерирует строки.

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

Для работы в Java вы должны передавать объекты как значения для заполнителей в подготовленном выражении, а не как текст внутри объекта String.

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

Если вы настаиваете на использовании простого текста, а не объектов, используйте форматирование SQL для ввода даты и времени. Я просто взял бы вывод ISO 8601, сгенерированный по умолчанию в java.time , и заменил T пробелом.

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

В качестве альтернативы, вы можете сгенерировать этот текст, используяDateTimeFormatter объект. Переполнение стека поиска, поскольку это уже было рассмотрено много раз.

Момент

У вас есть еще одна важная проблема в вашем коде. Использование вами слова «отметка времени» предполагает, что вы пытаетесь отследить момент, определенный момент на временной шкале. Ваша входная строка не может этого сделать. В вашем вводе отсутствует контекст offset-from-UTC (количество часов-минут-секунд вперед / позади основного меридиана) или часовой пояс ( имяв Continent/Region формате ).

Возьмем, к примеру, ваш ввод 10 утра. У нас нет никакой возможности узнать, имели ли вы в виду 10:00 в Токио, Япония или 10:00 в Толедо, Огайо, США, два совершенно разных момента с разницей в несколько часов.

Если вы отслеживаете моменты, вы должны использовать:

  • Столбец базы данных типа, похожего на стандарт SQL TIMESTAMP WITH TIME ZONE.
  • Один из этих Javaклассы: Instant, OffsetDateTime или ZonedDateTime (требуется только OffsetDateTime для поддержки в JDBC 4.2).

Пример:

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

Комучтобы представить момент в виде текста, следует использовать формат ISO 8601, заканчивающийся либо Z (для UTC, смещение нуля), либо смещением, например +05:30, либо смещением, за которым следует имя часового пояса в квадратных скобках,Последнее является нестандартным расширением ISO 8601, используемым классом java.time.ZonedDateTime.

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

JDBC 4.2 требует поддержки OffsetDateTime, но не Instant. Ваш драйвер JDBC может поддерживать Instant, но если нет, конвертировать.

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

При отслеживании моментов никогда не используйте тип базы данных, схожий со стандартным типом SQL TIMESTAMP WITHOUT TIME ZONE. И никогда не используйте Java-класс LocalDateTime на мгновение. У обоих намеренно отсутствует контекст часового пояса или смещения от UTC.

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

0 голосов
/ 23 декабря 2019

Пожалуйста, следуйте форматам даты ISO, чтобы Oracle принял ее как дату.

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

Синтаксис - -YYYY-MM-DD hh:mi:ss.SS

...