Отфильтровать записи, которые не имеют формат даты oracle - PullRequest
0 голосов
/ 13 июля 2020

Как мне отфильтровать записи, которые можно преобразовать только на дату, используя to_date('31-May-2019 00:00:00', 'DD-MON-YYYY HH24:MI:SS')

WITH dates   AS (
SELECT '0201-05-31 00:00:00' dates_col FROM dual UNION ALL
SELECT '31-May-2019 00:00:00' FROM dual UNION ALL
SELECT 'TEXT' FROM dual UNION ALL
SELECT '15-May-2019 00:00:00' FROM dual UNION ALL
SELECT '01-Apr-2019 00:00:00' FROM dual UNION ALL
SELECT '01-Apr-2019' FROM dual 
) SELECT * FROM dates  WHERE dates_col = ???

из приведенного выше примера запроса, я ожидаю результатов ниже

31-May-2019 00:00:00
15-May-2019 00:00:00
01-Apr-2019 00:00:00
01-Apr-2019

как мне добиться этого в oracle.

Причина, по которой я хочу это сделать: я получаю необработанные данные и загружаю их в таблицу перед их очисткой, чтобы вставить чистую данные в итоговую таблицу.

Ответы [ 4 ]

3 голосов
/ 13 июля 2020

Вы можете использовать встроенную функцию, чтобы проверить, действительна ли дата. Как это:

WITH 
FUNCTION is_valid_date (date_str_i VARCHAR2, format_i VARCHAR2) RETURN VARCHAR2
/* check if date is valid */
AS
  l_dummy_dt DATE;
BEGIN
  SELECT TO_DATE(date_str_i,format_i) INTO l_dummy_dt FROM DUAL;
  RETURN 'Y';
EXCEPTION WHEN OTHERS THEN
  RETURN 'N';
END; 
dates  AS (
SELECT '0201-05-31 00:00:00' dates_col FROM dual UNION ALL
SELECT '31-May-2019 00:00:00' FROM dual UNION ALL
SELECT 'TEXT' FROM dual UNION ALL
SELECT '15-May-2019 00:00:00' FROM dual UNION ALL
SELECT '01-Apr-2019 00:00:00' FROM dual UNION ALL
SELECT '01-Apr-2019' FROM dual 
) SELECT *
  FROM dates
 WHERE is_valid_date(dates_col,'DD-MON-YYYY HH24:MI:SS') = 'Y';

2 голосов
/ 13 июля 2020

Ах, старые добрые VARCHAR2 даты ... и радость, которая с ними приходит.

Один из вариантов - создать функцию, которая попытается преобразовать эти значения в даты. Если получится - нормально, все нормально. В противном случае это не так. Например:

SQL> create or replace function f_datum_ok_01 (par_datum in varchar2) return number
  2  is
  3    l_datum date;
  4  begin
  5    l_datum := to_date(par_datum,
  6                       'dd-mon-yyyy hh24:mi:ss',
  7                       'nls_date_language = english');
  8    return 1;
  9  exception
 10    when others then
 11      return 0;
 12  end f_datum_ok_01;
 13  /

Function created.

Тестирование:

SQL> select datum, f_datum_ok_01(datum) from test;

DATUM                          F_DATUM_OK_01(DATUM)
------------------------------ --------------------
0201-05-31 00:00:00                               0
31-May-2019 00:00:00                              1
TEXT                                              0
15-May-2019 00:00:00                              1
01-Apr-2019 00:00:00                              1
01-Apr-2019                                       1

6 rows selected.

SQL>

Строки, для которых функция возвращает 1 приемлемы.

  • Недостаток: может быть медленным для больших количество данных (переключение контекста).
  • Преимущество: вы можете добавлять другие допустимые форматы и также принимать эти значения.
1 голос
/ 14 июля 2020

Начиная с 12.2 синтаксис: to_date([expression] default null on conversion error, '[format]'):

with dates (dates_col) as
     ( select '0201-05-31 00:00:00' from dual union all
       select '31-May-2019 00:00:00' from dual union all
       select 'TEXT' from dual union all
       select '15-May-2019 00:00:00' from dual union all
       select '01-Apr-2019 00:00:00' from dual union all
       select '01-Apr-2019' from dual )
select dates_col
     , to_date(dates_col default null on conversion error, 'DD-MON-YYYY HH24:MI:SS') as converted
from   dates;

DATES_COL            CONVERTED
-------------------- -----------
0201-05-31 00:00:00  
31-May-2019 00:00:00 31/05/2019
TEXT                 
15-May-2019 00:00:00 15/05/2019
01-Apr-2019 00:00:00 01/04/2019
01-Apr-2019          01/04/2019
1 голос
/ 13 июля 2020

Начиная с Oracle 12.2, вы можете использовать специальную функцию VALIDATE_CONVERSION: https://docs.oracle.com/en/database/oracle/oracle-database/12.2/sqlrf/VALIDATE_CONVERSION.html#GUID -DC485EEB-CB6D-42EF-97AA-4487884CB2CD

SELECT VALIDATE_CONVERSION(1000 AS BINARY_DOUBLE)
  FROM DUAL;

SELECT VALIDATE_CONVERSION('1234.56' AS BINARY_FLOAT)
  FROM DUAL;

SELECT VALIDATE_CONVERSION('July 20, 1969, 20:18' AS DATE,
    'Month dd, YYYY, HH24:MI', 'NLS_DATE_LANGUAGE = American')
  FROM DUAL;

SELECT VALIDATE_CONVERSION('200 00:00:00' AS INTERVAL DAY TO SECOND)
  FROM DUAL;

SELECT VALIDATE_CONVERSION('P1Y2M' AS INTERVAL YEAR TO MONTH)
  FROM DUAL;

SELECT VALIDATE_CONVERSION('$100,00' AS NUMBER,
    '$999D99', 'NLS_NUMERIC_CHARACTERS = '',.''')
  FROM DUAL;

SELECT VALIDATE_CONVERSION('29-Jan-02 17:24:00' AS TIMESTAMP,
    'DD-MON-YY HH24:MI:SS')
  FROM DUAL;

SELECT VALIDATE_CONVERSION('1999-12-01 11:00:00 -8:00'
    AS TIMESTAMP WITH TIME ZONE, 'YYYY-MM-DD HH:MI:SS TZH:TZM')
  FROM DUAL;

SELECT VALIDATE_CONVERSION('11-May-16 17:30:00'
    AS TIMESTAMP WITH LOCAL TIME ZONE, 'DD-MON-YY HH24:MI:SS')
  FROM DUAL; 

Также с 12.2 to_date имеет дополнительные параметры "по умолчанию ... при ошибке преобразования: https://docs.oracle.com/en/database/oracle/oracle-database/12.2/sqlrf/TO_DATE.html#GUID -D226FA7 C -F7AD-41A0-BB1D-BD8EF9440118

SELECT TO_DATE('Febuary 15, 2016, 11:00 A.M.'
       DEFAULT 'January 01, 2016 12:00 A.M.' ON CONVERSION ERROR,
       'Month dd, YYYY, HH:MI A.M.') "Value"
  FROM DUAL;

Value
---------
01-JAN-16

Таким образом, вы можете указать специальное значение для таких случаев, например Null.

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