Regexp_replace WITH DECIMAL 返回错误 ORA-01722 "Invalid Number"
Regexp_replace WITH DECIMAL is returning error ORA-01722 "Invalid Number"
在 Oracle 中我有这样的代码:
regexp_replace(DESCRIPTION_FIELD, '[^0-9.]+', '')
工作正常,但现在出现错误:
ORA-01722 "Invalid Number".
删除小数点可以修复此问题,但会从返回值中删除小数点。我猜最近添加了一些不良数据。解决方案?
如果您会话的 NLS_NUMERIC_CHARACTERS 的小数点设置错误,通常会出现此错误。
您可以使用此更改会话设置:
alter session set NLS_NUMERIC_CHARACTERS = '.,';
或
alter session set NLS_NUMERIC_CHARACTERS = ',.';
这将仅为您的当前会话设置小数点和组分隔符。
或者您的 select 语句中有一个更通用的解决方案,该解决方案将始终假定为“.”。作为来自 table 的数据中的小数点。并将显示您会话的带小数点的数字。
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>;
regexp_replace()
没有产生那个错误;问题是当您将该替换的结果转换为数字时。例如,对于原始值 XYZ2626...266.88
,您的模式返回 2626...266.88
,而 to_number('2626...266.88')
抛出 ORA-01722。
by finding numbers with a format of "Some numbers, a decimal, then two numbers"
您可以寻找那个而不是试图排除其他字符:
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]*)?$', '') 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]*
以确保不会发生这种情况。该组合包含在第二个分组中以允许它是可选的(后跟 ?
)- 否则没有任何看起来像货币金额的值将不加改变地传递,这也可能会出错。
在 Oracle 中我有这样的代码:
regexp_replace(DESCRIPTION_FIELD, '[^0-9.]+', '')
工作正常,但现在出现错误:
ORA-01722 "Invalid Number".
删除小数点可以修复此问题,但会从返回值中删除小数点。我猜最近添加了一些不良数据。解决方案?
如果您会话的 NLS_NUMERIC_CHARACTERS 的小数点设置错误,通常会出现此错误。
您可以使用此更改会话设置:
alter session set NLS_NUMERIC_CHARACTERS = '.,';
或
alter session set NLS_NUMERIC_CHARACTERS = ',.';
这将仅为您的当前会话设置小数点和组分隔符。
或者您的 select 语句中有一个更通用的解决方案,该解决方案将始终假定为“.”。作为来自 table 的数据中的小数点。并将显示您会话的带小数点的数字。
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>;
regexp_replace()
没有产生那个错误;问题是当您将该替换的结果转换为数字时。例如,对于原始值 XYZ2626...266.88
,您的模式返回 2626...266.88
,而 to_number('2626...266.88')
抛出 ORA-01722。
by finding numbers with a format of "Some numbers, a decimal, then two numbers"
您可以寻找那个而不是试图排除其他字符:
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]*)?$', '') 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]*
以确保不会发生这种情况。该组合包含在第二个分组中以允许它是可选的(后跟 ?
)- 否则没有任何看起来像货币金额的值将不加改变地传递,这也可能会出错。