Как найти, какая запись вызывает ORA-01843: недопустимый месяц, когда объем данных огромен? - PullRequest
2 голосов
/ 09 марта 2020

Я не могу сосредоточиться на записи, которая вызывает проблему с недопустимым месяцем, хотел бы знать, есть ли более простой способ найти данные, вызывающие проблему, вместо ручной проверки всего один за другим?

Редактировать:

Пример данных (поставляется в виде текста):

1/17/2019 12:00:00 AM

Преобразование в метку времени:

to_timestamp(tested_date, 'MM/DD/YYYY HH:MI:SS AM')

Ответы [ 5 ]

6 голосов
/ 09 марта 2020

Начиная с Oracle 12.2, вы можете использовать validate_conversion(), чтобы найти недопустимые строки даты:

select tested_date
from mytable
where validate_conversion(tested_date as timestamp, 'MM/DD/YYYY HH:MI:SS AM') = 0

С документация :

VALIDATE_CONVERSION определяет, можно ли expr преобразовать в указанный тип данных. Если expr может быть успешно преобразовано, то эта функция возвращает 1; в противном случае эта функция возвращает 0.

2 голосов
/ 09 марта 2020

Вы можете создать пользовательскую функцию для проверки каждой строки даты:

CREATE FUNCTION is_valid_date(
  date_string IN VARCHAR2,
  format_model IN VARCHAR2 DEFAULT 'MM/DD/YYYY HH12:MI:SS AM'
) RETURN NUMBER
IS
  v_date DATE;
BEGIN
  v_date := TO_DATE( date_string, format_model );
  RETURN 1;
EXCEPTION
  WHEN OTHERS THEN
    RETURN 0;
END;
/

Затем используйте:

SELECT tested_date
FROM   your_table
WHERE  is_valid_date( tested_date ) = 0;

Чтобы найти строки с ошибками при конвертации.

(Примечание. В Oracle оба типа данных DATE и TIMESTAMP имеют временные компоненты, поэтому вам не нужно преобразовывать строку в TIMESTAMP и просто преобразовать ее в DATE . TIMESTAMP типы данных могут иметь необязательные доли секунды или часовой пояс, в то время как DATE типы данных имеют только год до целых секунд.)

1 голос
/ 09 марта 2020

Я нашел это решение, которое работает.

1) Создать функцию

create function test_date(d varchar2) return varchar2
is
  v_date date;
begin
  select to_timestamp(d,'MM/DD/YYYY HH:MI:SS AM') into v_date from dual;
  return 'Valid';
  exception when others then return 'Invalid';
end;

2)

select your_date_col, test_date(your_date_col)
from your_table;
0 голосов
/ 10 марта 2020

Если строки должны быть в формате 'MM/DD/ .....', то вы можете сделать что-то вроде этого - найти строки, у которых есть что-то, отличное от 1 до 12, до первого sla sh (или, возможно, 01 et c) 1007 * что делать с неверными данными.

0 голосов
/ 09 марта 2020

Возможно, вы могли бы использовать regexp_like. Я пробовал это для даты выборки, и она, кажется, работает:

select '1/17/2019 12:00:00 AM' as date_str
from dual
where REGEXP_LIKE('1/17/2019 12:00:00 AM', 
                  '^[0-9]{1,2}/[0-9]{1,2}/[0-9]{4} [0-9]{2}:[0-9]{2}:[0-9]{2} [A-Z]{2}')

Если вы хотите проверить все записи, которые не соответствуют формату, вы можете использовать NOT перед regexp_like:

select '1/17/2019 12:00:00 AM' as date_str
from dual
where not REGEXP_LIKE('1/17/2019 12:00:00 AM', 
                  '^[0-9]{1,2}/[0-9]{1,2}/[0-9]{4} [0-9]{2}:[0-9]{2}:[0-9]{2} [A-Z]{2}')

В основном он проверяет следующий формат в строке "01/01/0000 00:00:00 AA". 0 обозначает число, A обозначает алфавит, 1 обозначает необязательный номер (поскольку дата и месяц могут состоять из 1 или 2 цифр). Во всех остальных случаях условие не выполнится. Вы можете использовать это, чтобы получить записи, которые не в необходимом формате.

Надеюсь, это поможет.

...