Вы можете использовать регулярное выражение для определения правильного числа или нет. Затем, если он действителен, замените запятую нулями, а затем преобразуйте ее в число. В приведенных ниже запросах используется следующее регулярное выражение:
'^(\d{1,3})(\,\d{3})*(\.\d{2}|\.?)$'
Разбивается следующим образом
- ^ (\ d {1,3}) --- в начале строки 1-3 цифры
- (\, \ d {3}) * --- с последующим 0 или более запятыми, за которыми следуют 3 цифры
- (. \ D {2} |.?) --- с последующим десятичным знаком и двумя цифрами ИЛИ (|) необязательный десятичный знак
$ --- конец строки
Демонстрация:
with test (num, expected)
as (select '999,999,999,999.00', 'valid' from dual union all
select '999,99,999,999.00', 'invalid' from dual union all
select '999.00', 'valid' from dual union all
select '99', 'valid' from dual union all
select '9,999.', 'valid' from dual union all
select '9,999..0', 'invalid' from dual union all
select '999,99999,999.00', 'invalid' from dual
)
select num
, expected
, case when regexp_like(num,'^(\d{1,3})(\,\d{3})*(\.\d{2}|\.?)$')
then to_char(to_number(replace(num,',',null)))
else 'Not Valid Number'
end converted
from test;
В режиме реального времени вам не нужна структура "to_char (to_number ..."). Это использовалось для демонстрации / тестирования, так как и тогда, и тогда оператор case должен приводить к одному и тому же типу данных. Живая версия будет выглядеть примерно так:
with test (num)
as (select '999,999,999,999.00' from dual union all
select '999,99,999,999.00' from dual union all
select '999.00' from dual union all
select '99' from dual union all
select '9,999.' from dual union all
select '9,999..0' from dual union all
select '999,99999,999.00' from dual
)
select to_number(replace(num, ',', null))
from test
where regexp_like(num,'^(\d{1,3})(\,\d{3})*(\.\d{2}|\.?)$');