Найти неверные номера - Oracle SQL - PullRequest
1 голос
/ 01 июня 2019

У меня есть таблица:

table1

column_name    value
Test1          80933Y355220
Test1          8093363X5220
Test1          809336355220
Test1          80.98
Test1          -80.98

Test2          1234
Test2          abc
Test2          12-23-09

Мне нужно идентифицировать все недопустимые числовые значения, присутствующие в столбце value

Вывод должен быть:

column_name    value
Test1          80933Y355220
Test1          8093363X5220

Test2          abc
Test2          12-23-09

Есть ли способ получить этот список?

Ответы [ 3 ]

3 голосов
/ 01 июня 2019

Обычный способ решить эту проблему с помощью пользовательской функции:

create or replace function is_number (p_str in varchar2) return varchar2 is
n number;
rv varchar2(1);
begin
  begin
    n := to_number(p_str);
    rv := 'Y';
  exception
    when others then
      rv := 'N';
  end;
  return rv;
end;
/

select column_name, value, is_number(value) as is_number
from table1
where is_number(value) = 'N'
/

В Oracle 12c R2 мы приобрели встроенную функцию для этого: validate_conversion(), которая обрабатывает множество типов данных. Узнать больше .

select column_name
       , value
from table1
where validate_conversion(value as number) = 0
/

Вот демо на db <> fiddle .

Решения Regex сложно найти правильное решение. Легко сформулировать выражения, которые исключают действительные числа (такие как -80.98) или включают не числа (такие как (12-34-56). Даже мы правильно понимаем этот бит (как решение решения Гордона ), что происходит, если мы хотим разрешить десятичные разделители или символы валюты? Или научную запись? Это грязное регулярное выражение. UDF легко расширить для обработки маски форматирования, и validate_conversion() делает это изначально:

SELECT VALIDATE_CONVERSION('$100,00' AS NUMBER,
         '$999D99', 'NLS_NUMERIC_CHARACTERS = '',.''')
FROM DUAL;
1 голос
/ 02 июня 2019

Просто, чтобы дать ответ Oracle 12.1, он не имеет validate_conversion или on conversion error предложения to_date, но поддерживает PL/ SQL работает в предложении WITH , что позволяет что-то вроде этого:

with function is_number(str varchar2) return varchar2
     as
         n number;
     begin
         n := str; return 'Y';
     exception
         when others then return 'N';
     end;
select d.column_name
     , d.value
from   demo d
where  is_number(d.value) = 'N'
1 голос
/ 01 июня 2019

Я бы использовал regexp_like() с этим шаблоном:

SELECT column_name, value
FROM table1
WHERE  NOT REGEXP_LIKE(value, '^[-]?[0-9]*[.]?[0-9]*$')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...