Очистка столбца Oracle Date - PullRequest
       1

Очистка столбца Oracle Date

1 голос
/ 02 ноября 2010

У меня есть таблица1 (DueDate varchar2 (20)). Он содержит тысячи данных в другом формате с некоторыми неверными данными, такими как символы.

например.

YYYYMMDD,
MM/DD/YYYY,
MM-DD-YYYY,
M/D/YYYY,
'ABCD'
YYYYMMD,
YYYYMDD,

Теперь я должен был получить даты, которые просрочены на одну неделю. Как мне это сделать?

Спасибо за вашу помощь.

Ответы [ 3 ]

6 голосов
/ 02 ноября 2010

Это одна из причин, по которой хранение информации о дате в символьном поле является плохой идеей.

Самый простой вариант - создать функцию, которая пытается преобразовать строку в дату, используя форматы в любом порядке приоритетов (т. Е. 010203 2 января 2003 г. или 3 февраля 2001 г. или что-то еще), и перехватывает исключения. , Что-то вроде

CREATE OR REPLACE FUNCTION my_to_date( p_str IN VARCHAR2 )
  RETURN DATE
IS
  l_date DATE;
BEGIN
  l_date := to_date( p_str, 'YYYYMMDD' );
  RETURN l_date;
EXCEPTION
  WHEN others THEN
    BEGIN
      l_date := to_date( p_str, 'MM/DD/YYYY' );
      RETURN l_date;
    EXCEPTION 
      WHEN others
      THEN
        RETURN null;
    END;
END;

, который работает что-то вроде

SQL> CREATE OR REPLACE FUNCTION my_to_date( p_str IN VARCHAR2 )
  2    RETURN DATE
  3  IS
  4    l_date DATE;
  5  BEGIN
  6    l_date := to_date( p_str, 'YYYYMMDD' );
  7    RETURN l_date;
  8  EXCEPTION
  9    WHEN others THEN
 10      BEGIN
 11        l_date := to_date( p_str, 'MM/DD/YYYY' );
 12        RETURN l_date;
 13      EXCEPTION
 14        WHEN others
 15        THEN
 16          RETURN null;
 17      END;
 18  END;
 19  /

Function created.

SQL> select my_to_date( '19000101' ) from dual;

MY_TO_DAT
---------
01-JAN-00

SQL> ed
Wrote file afiedt.buf

  1* select my_to_date( '01/02/2005' ) from dual
SQL> /

MY_TO_DAT
---------
02-JAN-05

Конечно, вам придется кодировать полный набор допустимых форматов даты в вашем коде, я просто обрабатываю первые два в вашем списке.

1 голос
/ 02 ноября 2010

Этот ответ основан на ответе Джастина Кейва.Если вы создадите другой столбец, который является полем даты, вы можете сделать что-то вроде следующего:

UPDATE table1 SET DueDate2 = my_to_date(DueDate) 
   WHERE DueDate2 IS NULL AND DueDate IS NOT NULL;

Затем вы можете повторно запустить это обновление после каждого изменения формата даты в функции.Вам придется остановиться, когда все не преобразованные даты являются недействительными (например, «ABCD»).

0 голосов
/ 27 января 2018

Решение Pure SQL для Oracle 12.2, где удобная опция default null on conversion error избавляет от необходимости писать функции и обрабатывать исключения:

with demo (date_string) as
     ( select '2018081' from dual union all
       select '01/8/2018' from dual union all
       select '01-8-2018' from dual union all
       select 'ABCD' from dual union all
       select '2018-08-01' from dual union all
       select '2018-01-8' from dual union all
       select '2017081' from dual union all
       select '01-AUG-2018' from dual
     )
select t.date_string
     , coalesce
       ( to_date(t.date_string default null on conversion error)
       , case sys_context('USERENV','NLS_TERRITORY')
              when 'AMERICA' then to_date(t.date_string default null on conversion error,'MM/DD/YYYY')
              else to_date(t.date_string default null on conversion error,'DD/MM/YYYY')
         end
       , to_date(t.date_string default null on conversion error,'DD/MM/YYYY')
       , to_date(t.date_string default null on conversion error,'YYYY/MM/DD')
       , to_date(t.date_string default null on conversion error,'YYYYMMDD')
       , to_date(t.date_string default null on conversion error,'DD/MON/YYYY')
       ) as converted_date
from   demo t

Результаты:

DATE_STRING CONVERTED_DATE
----------- --------------
2018081     01-AUG-2018
01/8/2018   08-JAN-2018
01-8-2018   08-JAN-2018
ABCD
2018-08-01  01-AUG-2018
2018-01-8   08-JAN-2018
2017081     01-AUG-2017
01-AUG-2018 01-AUG-2018

Первый тестне указывает какой-либо формат для использования сеанса по умолчанию (DD-MON-RRRR и т. д.).

Следующий тест пытается обработать североамериканскую привычку ставить месяц первым.(Я не уверен, что sys_context('USERENV','NLS_TERRITORY') = 'AMERICA' является надежным тестом, так как он, как правило, является настройкой по умолчанию, независимо от фактической территории. Однако он иллюстрирует, как вы можете ввести некоторую условную логику при желании.)

to_date довольно прост в отношении символов-разделителей, поэтому я не указал различные форматы для DD-MON-YYYY против DD/MON/YYYY и т. Д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...