Regexp_replace WITH DECIMAL返回错误ORA-01722“无效数字”

问题描述 投票:0回答:2

在Oracle中我有这个代码:

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

工作正常,但现在我收到错误:

ORA-01722“无效编号”。

删除小数会修复此问题,但会从返回值中删除小数。我猜最近有一些不好的数据。解决方案?

sql regex oracle extract currency
2个回答
1
投票

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
投票

如果会话的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>;

编辑

如果在字符串中找到更多的小数点,并且您可以接受跳过某些小数点,则可能会有效。

select to_number(regexp_substr(regexp_replace(ESCRIPTION_FIELD, '[^0-9.]+', ''),'([0-9]*.[0-9]*)'), '999999999999.99999', 'NLS_NUMERIC_CHARACTERS = ''.,''') from <your table>;
© www.soinside.com 2019 - 2024. All rights reserved.