Как позволить SQL быть более гибким в отношении того, что вменяется, «RR-MM-DD HH.MI.SSXFF AM» создает [22008] [1855] ORA-01855: AM / A.M. или PM / P.M. требуется - PullRequest
0 голосов
/ 02 июля 2018

Я должен ввести дату несколькими разными способами.

  1. to_timestamp('2015-10-06 0:00:00.0 AM', 'RR-MM-DD HH.MI.SSXFF AM')

и

  1. to_timestamp('2115-10-06 01:00:00.0 AM', 'RR-MM-DD HH.MI.SSXFF AM')

Ошибки для обоих

  1. ORA-01849: hour must be between 1 and 12

  2. [22008][1855] ORA-01855: AM/A.M. or PM/P.M. required

То, чего я пытаюсь достичь, - это возможность использовать 2115-10-06 01:00:00.0 AM или 2015-10-06 0:00:00.0 AM без этого, что дает мне ошибку об ограничениях здесь 'RR-MM-DD HH.MI.SSXFF AM'.

1 Ответ

0 голосов
/ 02 июля 2018

12-часовые часы не имеют 0-го часа.

Если вы хотите поддержать 0-й час в качестве псевдонима для 12-го часа, то вы можете написать пользовательскую функцию для замены 0 на 12:

SQL Fiddle

Настройка схемы Oracle 11g R2 :

CREATE FUNCTION parse_timestamp(
  in_string VARCHAR2
) RETURN TIMESTAMP
IS
  p_string    VARCHAR2(30) := in_string;
  c_fix_hours CHAR(61) := '^(\d{1,4}-\d\d?-\d\d? )00?(:[0-5]?\d:[0-5]?\d(\.\d+)? [AP]M)$';
BEGIN
  IF REGEXP_LIKE( p_string, c_fix_hours, 'i' ) THEN
    p_string := REGEXP_REPLACE( p_string, c_fix_hours, '\112\2', 1, 1, 'i' );
  END IF;
  RETURN TO_TIMESTAMP( p_string, 'RR-MM-DD HH12.MI.SSXFF AM' );
END;
/ 

Запрос 1 :

SELECT parse_timestamp(
         '2015-10-06 0:00:00.0 AM'
       ),
       parse_timestamp(
         '2115-10-06 01:00:00.0 AM'
       )
FROM   DUAL

Результаты :

| PARSE_TIMESTAMP('2015-10-060:00:00.0AM') | PARSE_TIMESTAMP('2115-10-0601:00:00.0AM') |
|------------------------------------------|-------------------------------------------|
|                    2015-10-06 00:00:00.0 |                     2115-10-06 01:00:00.0 |

Обновление Использование оператора CASE:

SQL Fiddle

Запрос 1 :

WITH test_data ( value ) AS (
  SELECT '2015-10-06 0:00:00.0 AM'  FROM DUAL UNION ALL
  SELECT '2115-10-06 01:00:00.0 AM' FROM DUAL UNION ALL
  SELECT '5-9-7 00:59:59.234 PM'    FROM DUAL
)
SELECT TO_TIMESTAMP(
         CASE
         WHEN REGEXP_LIKE( value, '^(\d{1,4}-\d\d?-\d\d? )00?(:[0-5]?\d:[0-5]?\d(\.\d+)? [AP]M)$', 'i' )
         THEN REGEXP_REPLACE( value, '^(\d{1,4}-\d\d?-\d\d? )00?(:[0-5]?\d:[0-5]?\d(\.\d+)? [AP]M)$', '\112\2', 1, 1, 'i' ) 
         ELSE value
         END,
         'RR-MM-DD HH12.MI.SSXFF AM'
       ) AS datetime
FROM   test_data

Результаты

|                DATETIME |
|-------------------------|
|   2015-10-06 00:00:00.0 |
|   2115-10-06 01:00:00.0 |
| 2005-09-07 12:59:59.234 |
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...