“安全”TO_NUMBER()

SELECT TO_NUMBER('*') FROM DUAL 

这显然给了我一个例外:

ORA-01722:无效的号码

有没有办法“跳过”,并得到0NULL呢?

整个问题:我有NVARCHAR2字段,其中包含数字,而不是几乎* )(如* ),我需要从列中select最大的数字。

是的,我知道这是一个可怕的devise,但这是我现在需要的…:-S

UPD

对于我自己,我已经解决了这个问题

 COALESCE(TO_NUMBER(REGEXP_SUBSTR(field, '^\d+')), 0) 

我找不到比这更好的东西:

 function safe_to_number(p varchar2) return number is v number; begin v := to_number(p); return v; exception when others then return 0; end; 
 COALESCE(TO_NUMBER(REGEXP_SUBSTR(field, '^\d+(\.\d+)?')), 0) 

也会得到比例大于等于0的数字(小数点右边的数字)。

 select COALESCE(TO_NUMBER(REGEXP_SUBSTR( field, '^(-|+)?\d+(\.|,)?(\d+)?$')), 0) from dual; 

它会将123转换为123 ,而将123a12a3转换0

适合原来的问题,而不是老的skool

 select a, decode(trim(translate(b,'0123456789.',' ')),null,to_number(b),0) from ( select '1' a, 'not a number' b from dual union select '2' a, '1234' b from dual ) 

滚动自己的正则expression式来testing一个数字可能有点麻烦,但下面的代码可能工作。 我认为由Gabe涉及用户定义的函数的另一个解决scheme是更强大的,因为你正在使用内置的Oraclefunction(和我的正则expression式可能不是100%正确),但它可能是值得一试:

 with my_sample_data as ( select '12345' as mynum from dual union all select '54-3' as mynum from dual union all select '123.4567' as mynum from dual union all select '.34567' as mynum from dual union all select '-0.3462' as mynum from dual union all select '0.34.62' as mynum from dual union all select '1243.64' as mynum from dual ) select mynum, case when regexp_like(mynum, '^-?\d+(\.\d+)?$') then to_number(mynum) end as is_num from my_sample_data 

这将给出以下输出:

 MYNUM IS_NUM -------- ---------- 12345 12345 54-3 123.4567 123.4567 .34567 -0.3462 -0.3462 0.34.62 1243.64 1243.64 
 select DECODE(trim(TRANSLATE(replace(replace(A, ' '), ',', '.'), '0123456789.-', ' ')), null, DECODE(INSTR(replace(replace(A, ' '), ',', '.'), '.', INSTR(replace(replace(A, ' '), ',', '.'), '.') + 1), 0, DECODE(INSTR(replace(replace(A, ' '), ',', '.'), '-', 2), 0, TO_NUMBER(replace(replace(A, ' '), ',', '.'))))) A from (select '-1.1' A from DUAL union all select '-1-1' A from DUAL union all select ',1' A from DUAL union all select '1..1' A from DUAL) A; 

这段代码不包括这样的string:-1-1,1..1,12-2等等。 我没有在这里使用正则expression式。

Oracle Database 12c Release 2您可以使用TO_NUMBERDEFAULT ... ON CONVERSION ERROR

 SELECT TO_NUMBER('*' DEFAULT 0 ON CONVERSION ERROR) AS "Value" FROM DUAL; 

CAST

 SELECT CAST('*' AS NUMBER DEFAULT 0 ON CONVERSION ERROR) AS "Value" FROM DUAL;