0

I have a field (column in Oracle) called X that has values like "a1b2c3", "abc", "1ab", "123", "156"

I wrote a sql query that returns only the X that holds pure numerical values with no letters; from the example above would be 123 and 156.

Query written using Oracle syntax:

select X from where REGEXP_LIKE(X, '^[[:digit:]]+$')

Result:

123, 156

Additionally I need to write a query to get the value between 100 and 150.

How could I write such a query in Oracle? Something like below:

select X from where REGEXP_LIKE(X, '^[[:digit:]]+$') between 100 and 150
1
  • 1
    Can there be more than 3 digits? Commented Apr 10, 2017 at 10:40

3 Answers 3

2

regexp_like() is a condition, so you can't compare it with anything. You can use the regexp_substr() function instead:

where regexp_substr(x, '^[[:digit:]]+$') between 100 and 150

The value returned by the function is either null or a string of digits that can be (implicitly) converted to a number for comparison.

Demo with your sample data:

with your_table (x) as (
  select 'a1b2c3' from dual
  union all select 'abc' from dual
  union all select '1ab' from dual
  union all select '123' from dual
  union all select '156' from dual
)
select x from your_table
where regexp_substr(x, '^[[:digit:]]+$') between 100 and 150;

X     
------
123
Sign up to request clarification or add additional context in comments.

Comments

0
CREATE FUNCTION is_number (p_string IN VARCHAR2)
   RETURN INT
IS
   v_new_num NUMBER;
BEGIN
   v_new_num := TO_NUMBER(p_string);
   RETURN 1;
EXCEPTION
WHEN VALUE_ERROR THEN
   RETURN 0;
END is_number;

then use this in query

select X from where is_number(X)=1 and TO_Number(X) between 100 and 150

4 Comments

Why not return the parsed number from the function or NULL on an error?
function is used to check if value is number or not if it is numeric then returns 1 else it will return 0
There's no guarantee your function call will be evaluated first here either, so this is still likely to get ORA-01722. With MTO's suggestion it would be OK though.
I know what it does but you could simplify it to: CREATE FUNCTION check_number (p_string IN VARCHAR2) RETURN NUMBER IS BEGIN RETURN TO_NUMBER(p_string); EXCEPTION WHEN VALUE_ERROR THEN RETURN NULL; END check_number; and just use that in the BETWEEN filter. As @AlexPoole noted you will get an ORA-01722 if the TO_NUMBER check is performed before the IS_NUMBER check.
0

Try this.

with tbl(X) as
(select 'a1b2c3' from dual union all select
'abc' from dual union all select
'123' from dual union all select
'156' from dual )
select * from (
   select * from tbl where
     REGEXP_LIKE(X, '^[[:digit:]]+$') 
               ) t
where x between 100 and 150

4 Comments

This will also get ORA-01722 if the (implicit) to_number is evaluated before the regexp_like(). Try it with a table, not a CTE.
Oh. let me try.
You are right! CTE behavior is more casual it seems. Editing my answer back to previous using subquery. Anyways it is moot now because of your answer.
Actually I get the same with your original query too; I guess the predicate is being pushed into the subquery, unhelpfully. Depends what mood the optimiser is in I suppose *8-)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.