Ответ @GordonLinoff работает с показанными вами примерами данных, но будет ошибка с ORA-01722 «недопустимый номер», если у вас есть какие-либо значения, которые не представляют числа. В ваших примерах данных есть только хорошие значения, но вы сказали, что для вашего реального поля «ожидается любой тип данных, например дата, числа, буквенно-цифровые и т. Д.».
Вы можете обойти это с помощью функции, которая пытается преобразовать сохраненное строковое значение в число и возвращает null, если получает это исключение. Простой пример:
create function safe_to_number (p_str varchar2) return number is
begin
return to_number(p_str);
exception
when value_error then
return null;
end;
/
Затем вы можете сделать
select *
from test
where safe_to_number(val) not between 0 and 128;
VAL
----------
129
200
Все, что не может быть преобразовано и вызывает исключение ошибки значения ORA-06502, будет рассматриваться как нуль, который не находится ни между, ни не между любыми указанными вами значениями.
Если вам нужно проверить диапазоны дат, вы можете сделать что-то подобное, но возможны другие ошибки, и у вас могут быть даты в нескольких форматах; вам нужно будет объявить исключения и инициализировать их известными номерами ошибок а> чтобы поймать те, которые вы ожидаете увидеть. Это не завершено, но вы можете начать с чего-то вроде:
create function safe_to_date (p_str varchar2) return date is
l_formats sys.odcivarchar2list;
format_ex_1 exception;
format_ex_2 exception;
format_ex_3 exception;
format_ex_4 exception;
format_ex_5 exception;
pragma exception_init(format_ex_1, -1840);
pragma exception_init(format_ex_2, -1841);
pragma exception_init(format_ex_3, -1847);
pragma exception_init(format_ex_4, -1858);
pragma exception_init(format_ex_5, -1861);
-- add any others you might get
begin
-- define all expected formats
l_formats := sys.odcivarchar2list('YYYY-MM-DD', 'DD/MM/YYYY', 'DD-MON-RRRR'); -- add others
for i in 1..l_formats.count loop
begin
return to_date(p_str, l_formats(i));
exception
when format_ex_1 or format_ex_2 or format_ex_3 or format_ex_4 or format_ex_5 then
-- ignore the exception; carry on and try the next format
null;
end;
end loop;
-- did not match any expected formats
return null;
end;
/
select *
from test
where safe_to_date(val) not between date '2016-02-01' and date '2016-02-29';
Хотя обычно я бы не использовал between
для дат; если у вас нет ни одного с указанным временем, то вам это сойдет с рук здесь.
Вы можете использовать when others
для перехвата любого исключения без необходимости объявлять их все, но даже в этом случае это потенциально опасно — если что-то ломается так, как вы не ожидаете, что захотите об этом знать, не скрыть.
Конечно, это наглядный пример того, почему вы должны хранить числовые данные в столбцах NUMBER, а даты — в полях DATE или TIMESTAMP — пытаться извлечь полезную информацию, когда все хранится в виде строк, беспорядочно, болезненно и неэффективно.
person
Alex Poole
schedule
21.03.2016