I have a table with this values:
ID VALUE
-----------------------
23559 200
23562 -1 & {14376}#-1
and I want to do to a select that if I cannot convert to number set NULL.
I have a table with this values:
ID VALUE
-----------------------
23559 200
23562 -1 & {14376}#-1
and I want to do to a select that if I cannot convert to number set NULL.
I generally use translate for this because it is such an odd corner case:
SELECT
CASE
WHEN NOT TRIM(TRANSLATE(COLUMN_NAME, '1234567890', ' ')) IS NULL THEN NULL
ELSE COLUMN_NAME
END AS "NUMERIC_COLUMN"
FROM
TABLE_NAME;
If necessary, that can be turned into a procedure, but I'm not sure that there would be terribly much benefit performance-wise.
You can create a function that tries to convert the string to a number and catches the exception. Something like
CREATE OR REPLACE FUNCTION my_to_number( p_str IN VARCHAR2 )
RETURN NUMBER
IS
l_num NUMBER;
BEGIN
BEGIN
l_num := to_number( p_str );
EXCEPTION
WHEN others THEN
l_num := null;
END;
RETURN l_num;
END;
Then you can
SELECT id, my_to_number( value )
FROM your_table
You could also use REGEXP_LIKE:
SELECT id
, CASE WHEN regexp_like(value,'^[0-9]+$') THEN TO_NUMBER(value)
ELSE NULL
END value
FROM your_table;
For example:
SQL> WITH q AS (
2 SELECT 1 ID, '200' col FROM dual
3 UNION
4 SELECT 2, '-1 & {14376}#-1' FROM dual
5 )
6 SELECT id, CASE WHEN regexp_like(col,'^[0-9]+$') THEN TO_NUMBER(col) ELSE NULL END TEST FROM q;
ID TEST
---------- ----------
1 200
2
With Oracle 12.2 this can be done a bit easier using the on conversion error
option:
select id, cast(value as number default null on conversion error) as value
from the_table;
Optionally you can also specify a format mask, similar to the to_number()
function.
I assume this would be faster than using a PL/SQL function, not sure about the performance compared to a case
with a regex. But it is definitely a lot shorter.
CREATE OR REPLACE FUNCTION asnumber(p_val IN VARCHAR2) RETURN NUMBER IS
l_val NUMBER;
BEGIN
l_val := TO_NUMBER(p_val);
RETURN l_val;
EXCEPTION WHEN VALUE_ERROR THEN
RETURN null;
END;