Reputation: 109
Table name SAMP_TAB
- it has only one column COL
of datatype varchar2
- with data like this:
COL
----
1234
abcd
098
12wer
345
These are the above sample values in that column.
Now I want to write a query which will return only numeric values from this column.
Desired output:
1234
098
345
I want to write that query without using any regex.
Upvotes: 2
Views: 81
Reputation: 146239
If you're using 12c R2 or later (and you should be) you can use the built-in function validate_conversion()
which is a safe way of determining whether a value can be converted to another datatype. Find out more.
Like this:
select * from samp_table
where validate_conversion(col as number) = 1
/
This approach has a major advantage over solutions using regex or translate()
in that it tests whether the string evaluates to a numeric value, whereas the other solutions would choke on, say, an exponential expression like 1.234E+10
. Or might pass an IP address like 127.0.0.1
.
If you have an earlier version of Oracle you can write a user-defined function which uses to_number()
to evaluate a passed parameter:
create or replace function is_number (p_str in varchar2) return pls_integer
is
rv pls_integer;
begin
declare
n number;
begin
n := to_number(p_str);
rv := 1; -- p_str is a number
exception
when others then
rv := 0; -- p_str is not a number
end;
return rv;
end;
/
You would call this function in the WHERE clause same as validate_conversion()
in the example above.
Upvotes: 4
Reputation: 65278
Splitting each character, extracting integers through filtering by ascii()
function as
ascii(<character>) between 48 and 57
, and recombining the strings might be another option :
with t as
(
select substr(col,level,1) as chr, level as lvl,
row_number() over (order by 0) as rn
from samp_tab
connect by level <= length(col)
and prior sys_guid() is not null
and prior col = col
), t2 as
(
select t.*, sum(case when lvl=1 then 1 else 0 end) over (order by rn) as rn2
from t
where ascii(chr) between 48 and 57
)
select listagg(chr) within group (order by rn2) as new_col
from t2
group by rn2;
Upvotes: 0
Reputation: 521289
Assuming you can't use regex, for some reason:
SELECT COL
FROM SAMP_TAB
WHERE TRIM(TRANSLATE(COL, '0123456789', ' ')) IS NULL;
If you can use regex, then use REGEXP_LIKE
with the pattern ^[0-9]+$
:
SELECT COL
FROM SAMP_TAB
WHERE REGEXP_LIKE (COL, '^[0-9]+$');
Upvotes: 2
Reputation: 142743
Alternatively:
SQL> with test (col) as
2 (select '1234' from dual union all
3 select 'abcd' from dual union all
4 select '098' from dual union all
5 select '12wer' from dual union all
6 select '1ab3' from dual union all
7 select '345' from dual
8 )
9 select col
10 from test
11 where translate(col, 'a0123456789', 'a') is null;
COL
-----
1234
098
345
SQL>
Upvotes: 0