2016-06-06 3 views
0

У меня есть столбец, в котором начинается строка: «Чикаго, Иллинойс, 20 апреля 2015 года — и т. Д. Текст здесь». Я хочу извлечь часть Date из этой строки в Oracle. Есть идеи, как это сделать. Я смог найти что-то для mm/dd/yyyy, как показано ниже, но не для длинного формата даты.Дата из строки oracle

SELECT REGEXP_SUBSTR(' the meeting will be on 8/8/2008', '[0-9]{1,}/[0-9]{1,}/[0-9]{2,}') FROM dual 
+0

будет дата всегда имеет тот же формат, например, 'full_month_name день, год'? – Timekiller

+0

Да, это правильно. – user747291

ответ

0

Если значение столбцы всегда начинаются с 'Chicago, IL, April 20, 2015 — and so on text here', то вы можете simly использовать SUBSTR вместо REGEXP_SUBSTR

SELECT 
    SUBSTR(column_name 
     ,INSTR(column_name, ',', 1, 2) + 1 
     ,INSTR(column_name, '—') - INSTR(column_name, ',', 1, 2) - 1 
    ) 
FROM 
    dual; 

Если нет, то вы могли бы использовать REGEXP_SUBSTR как и другие упоминания ответ, мой первоначальный ответ неверен, как @MTO комментарий

+0

Регулярное выражение будет соответствовать: 'Относительно точки 42, 1984 - фантастическая книга'. или даже '99, 0000'. – MT0

+0

МТО получил его, спасибо. @ user747291, вы должны обновить свой запрос в соответствии с другим ответом. Шахта изменена. –

+0

Ваш запрос 'SUBSTR/INSTR' будет работать только для 5-значных имен месяцев и двухзначных дней. Если вы хотите совместить «1 мая 1900 года» или «25 декабря 2016 года», то они не являются 14 символами. Он также полагается на дату добавления с дефис (не уверен, что это всегда так). – MT0

1

Ну, вы можете сделать прямой подход и использовать регулярное выражение, как в примере, который вы нашли:

SELECT 
    REGEXP_SUBSTR('Chicago, IL, April 20, 2015 - etc etc', '(January|February|March|April|May|June|July|August|September|October|November|December) [0-9]{1,2}, [0-9]{4}') 
FROM dual; 

Но это будет работать только в том случае, если все даты указаны в том же формате. Полное название месяца с первой буквой в верхнем регистре, пробел, день, запятая, пробел, 4-значный год. Если может быть больше одного пространства или вообще нет места, используйте \s* вместо пробелов в регулярном выражении. Если имя месяца не обязательно initcap, используйте initcap() для флага источника или без учета регистра для функции regexp_substr.

Кроме того, это поймает фиктивные даты, которые соответствуют формату, например «Апрель 99, 1234», вам придется отфильтровывать их позже.

2

Вы могли бы использовать:

SELECT TO_DATE(
      REGEXP_SUBSTR(
      'Chicago, IL, April 20, 2015 — and so on text here', 
      '(JANUARY|FEBRUARY|MARCH|APRIL|MAY|JUNE|JULY|AUGUST|SEPTEMBER|' 
       || 'OCTOBER|NOVEMBER|DECEMBER)' 
       || '[[:space:]]+([012]?[0-9]|3[01])' 
       || '[[:punct:][:space:]]+\d{4}', 
      1, 
      1, 
      'i' 
     ), 
      'MONTH DD YYYY' 
     ) 
FROM DUAL; 

Если вы хотите, чтобы проверить даты, а также (так что вы не получите сообщение об ошибке для February 29, 2001), то вы можете использовать определяемые пользователем функции:

CREATE FUNCTION parse_Date(
    in_string  VARCHAR2, 
    in_format  VARCHAR2 DEFAULT 'YYYY-MM-DD', 
    in_nls_params VARCHAR2 DEFAULT NULL 
) RETURN DATE DETERMINISTIC 
AS 
BEGIN 
    RETURN TO_DATE(in_string, in_format, in_nls_params); 
EXCEPTION 
    WHEN OTHERS THEN 
    RETURN NULL; 
END; 
/

И заменить TO_DATE(...) функции с PARSE_DATE(...)

+0

Более общий ответ, должен быть принят. Я бы предложил изменить '[12]?' На '[012]?', Чтобы поймать даты типа «01 апреля». Также он по-прежнему подвержен ошибкам, например, «31 февраля», но перехватывать все это с помощью регулярного выражения - это слишком много работы. – Timekiller

+0

@Timekiller Обновлен до '[012]', а также добавлен способ обработки ошибочных дат (адаптирован из [моего ответа здесь] (http://stackoverflow.com/a/35270553/1509264)). – MT0