Regexp_replace WITH DECIMAL возвращает ошибку ORA-01722 «Неверный номер» - PullRequest
0 голосов
/ 29 марта 2019

В Oracle у меня был этот код:

regexp_replace(DESCRIPTION_FIELD, '[^0-9.]+', '') 

это работало нормально, но теперь я получаю сообщение об ошибке:

ORA-01722 "Неверный номер".

Удаление десятичной дроби исправляет это, но удаляет десятичную с возвращаемого значения. Я предполагаю, что недавно были добавлены плохие данные. Решения?

Ответы [ 2 ]

1 голос
/ 29 марта 2019

regexp_replace() не генерирует эту ошибку; проблема в том, что вы приводите результат этой замены к числу. Например, для исходного значения XYZ2626...266.88 ваш шаблон возвращает 2626...266.88, а to_number('2626...266.88') выдает ORA-01722.

путем поиска чисел в формате «Некоторые числа, десятичное, затем два числа»

Вы можете искать это вместо того, чтобы пытаться исключить другие символы:

with your_table (description_field) as (
  select 'No money value' from dual
  union all
  select 'Some sensible 98765.43 value' from dual
  union all
  select '01234-1234545 54.00' from dual
  union all
  select 'XYZ2626...266.88' from dual
  union all
  select 'ABC-123.45XYZ' from dual
  union all
  select 'ABC123.45XYZ6.78' from dual
)
select description_field,
  regexp_replace(DESCRIPTION_FIELD, '[^0-9.]+', '') as original,
  regexp_replace(DESCRIPTION_FIELD, '.*?((-?\d+\.\d{2})[^0-9]*)?$', '\2') as new
from your_table;

DESCRIPTION_FIELD            ORIGINAL             NEW                 
---------------------------- -------------------- --------------------
No money value                                                        
Some sensible 98765.43 value 98765.43             98765.43            
01234-1234545 54.00          01234123454554.00    54.00               
XYZ2626...266.88             2626...266.88        266.88              
ABC-123.45XYZ                123.45               -123.45             
ABC123.45XYZ6.78             123.456.78           6.78                

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

Группа захвата (-?\d+\.\d{2}) ищет необязательный знак минуса, за которым следует любое количество цифр, за которым следует точка, за которой следуют ровно 2 цифры. Но это само по себе не помешает дальнейшим цифрам впоследствии, поэтому следует [^0-9]*, чтобы убедиться, что этого не произойдет. Эта комбинация заключена во вторую группу, чтобы сделать ее необязательной (за которой следует ?) - в противном случае значения без всего, что выглядит как денежная сумма, пропускаются без изменений, что также может привести к ошибке.

0 голосов
/ 29 марта 2019

Эта ошибка обычно возникает, если для вашей сессии в NLS_NUMERIC_CHARACTERS задана неправильная десятичная точка.

Вы можете изменить настройку для вашей сессии, используя это:

alter session set NLS_NUMERIC_CHARACTERS = '.,';

или

alter session set NLS_NUMERIC_CHARACTERS = ',.';

Это установит десятичный разделитель и разделитель групп только для вашей текущей сессии.

Или в вашем утверждении select есть более общее решение, которое всегда будет принимать '.' в виде десятичной точки в ваших данных из таблицы. И отобразит число с десятичной точкой для вашей сессии.

select to_number(regexp_replace(ESCRIPTION_FIELD, '[^0-9.]+', ''), '999999999999.99999', 'NLS_NUMERIC_CHARACTERS = ''.,''') from <your table>;

EDIT

Если в строке найдено больше десятичной точки, и вы можете принять, что некоторые пропущены, это может сработать.

select to_number(regexp_substr(regexp_replace(ESCRIPTION_FIELD, '[^0-9.]+', ''),'([0-9]*.[0-9]*)'), '999999999999.99999', 'NLS_NUMERIC_CHARACTERS = ''.,''') from <your table>;
...