django-unchained
django-unchained

Reputation: 844

Pattern Matching in Oracle SQL

I am trying to match some patterns and exclude some based on certain characters and lengths.

I want to return all 3 characters and 4 characters values:

Table:

+------+
| CODE |
+------+
|   11 |
|  11A |
|  11B |
| 11EF |
| 11AB |
+------+

EXPECTED OUTPUT:

+-----------------+
| EXPECTED OUTPUT |
+-----------------+
|             11A |
|             11B |
|            11AB |
+-----------------+

I've tried this but it returns all regardless of the conditions I mentioned above:

select REGEXP_SUBSTR('11EF','^[0-9]{1,2}[A-Z]{1,2}?')  from dual;

select REGEXP_SUBSTR('11','^[0-9]{1,2}[A-Z]{1,2}?')  from dual;

select REGEXP_SUBSTR('11A','^[0-9]{1,2}[A-Z]{1,2}?')  from dual;

Upvotes: 0

Views: 2399

Answers (3)

Gary_W
Gary_W

Reputation: 10360

This uses a case-insensitive REGEXP_LIKE() that matches a string consisting of 2 characters followed by a letter OR 2 characters followed any letter except E, followed by any letter except F.

with tbl(code) as (
  select '11' from dual union all
  select '11A' from dual union all
  select '11b' from dual union all
  select '11EF' from dual union all
  select '11FE' from dual union all
  select '11A#' from dual union all
  select '11BA' from dual union all
  select '1ZZZ' from dual union all  
  select NULL from dual union all
  select 'HELLO' from dual union all
  select 'A12' from dual
)
select code
from tbl
where regexp_like(code, '^((.{2}[A-Z])|(.{2}[A-D,F-Z][A-E,G-Z]))$', 'i');



CODE 
-----
11A  
11b  
11FE 
11BA 
1ZZZ 

5 rows selected.

EDIT: could be simplified a little to:

'^.{2}(([A-Z])|([A-D,F-Z][A-E,G-Z]))$'

Upvotes: 0

Zynon Putney II
Zynon Putney II

Reputation: 695

This worked for me on Oracle Live SQL:

create table temp( text varchar2(25));

INSERT INTO temp values ('11');
INSERT INTO temp values ('11A');
INSERT INTO temp values ('11B');
INSERT INTO temp values ('11EF');
INSERT INTO temp values ('11AB');
INSERT INTO temp values ('21ASDF');
INSERT INTO temp values ('31ASD');
INSERT INTO temp values ('251ASDF');
INSERT INTO temp values ('41ASDFDSF');

select text
from temp
where length(text) between 3 and 4
and (regexp_instr(text, '[[:alpha:]]', 3) > 0 or regexp_instr(text, '[[:alpha:]][[:alpha:]]', 3) > 0)
and substr(text, 3, 2) <> 'EF';

TEXT
11A
11B
11AB

Upvotes: 1

Dai
Dai

Reputation: 155035

I changed your regular-expression to this. It does not perform the EF-check in the regex but elsewhere in the query as that would make the regex far more complicated:

^(\d\d[A-Z])|(\d\d[A-Z]{2})$

And this query works for me in SqlFiddle.com:

SELECT
  text_col
FROM
  Foo
WHERE
  REGEXP_INSTR( text_col, '^(\d\d[A-Z])|(\d\d[A-Z]{2})$' ) > 0
  AND
  REGEXP_INSTR( text_col, 'EF$' ) = 0

Upvotes: 0

Related Questions