REGEXP_LIKE(문자열, 패턴 [, 옵션]) 은 참·거짓을 돌려주는 조건이다. SELECT 목록에 값처럼 쓸 수는 없고 WHERE·CASE WHEN 같은 조건 자리에 쓴다.
이 노트의 실습 환경인 Oracle 23ai 는 BOOLEAN 형이 생겨 SELECT REGEXP_LIKE(ENAME, 'A') FROM EMP 가 TRUE·FALSE 를 돌려준다. 시험 기준(그 이전 버전)에서는 SELECT 목록에 쓸 수 없다. 이 사이트의 실습장도 시험 기준을 따른다.
SELECT ENAME FROM EMP WHERE REGEXP_LIKE(ENAME, '^[AJ]') ORDER BY ENAME;
ENAME----------ADAMSALLENJAMESJONES
SELECT ENAME FROM EMP WHERE REGEXP_LIKE(ENAME, '(.)\1') ORDER BY ENAME;
ENAME----------ALLENMILLERSCOTT
(.) 가 아무 글자 하나를 잡고, \1 이 방금 잡은 글자와 같은 글자를 요구한다. ALLEN·MILLER 의 LL, SCOTT 의 TT 가 맞았다.
'LL|TT' 로 써도 같은 세 명이 나왔다. 역참조는 어떤 글자인지 몰라도 "같은 글자 두 번"을 찾는다는 점이 다르다.
이름이 정확히 네 글자인 사원이다.
SELECT ENAME FROM EMP WHERE REGEXP_LIKE(ENAME, '^.{4}$') ORDER BY ENAME;
ENAME----------FORDKINGWARD
^ 와 $ 를 빼고 '.{4}' 만 쓰면 14명이 모두 나왔다. 다섯 글자 이름 안에도 "연속한 네 글자"가 있기 때문이다.
SELECT (SELECT COUNT(*) FROM EMP WHERE ENAME LIKE 'A') AS LIKE_A, (SELECT COUNT(*) FROM EMP WHERE ENAME LIKE '%A%') AS LIKE_PCT, (SELECT COUNT(*) FROM EMP WHERE REGEXP_LIKE(ENAME, 'A')) AS REGEXP_A FROM DUAL;
REGEXP_INSTR 의 반환 옵션이 0(기본)이면 일치의 시작 위치, 1 이면 일치가 끝난 다음 위치다.
30번 부서 사원 이름에서 모음을 찾는다.
SELECT ENAME, REGEXP_SUBSTR(ENAME, '[AEIOU]') AS V1, REGEXP_SUBSTR(ENAME, '[AEIOU]', 1, 2) AS V2, REGEXP_INSTR(ENAME, '[AEIOU]') AS P1, REGEXP_COUNT(ENAME, '[AEIOU]') AS CNT FROM EMP WHERE DEPTNO = 30 ORDER BY ENAME;
ENAME V1 V2 P1 CNT---------- ---------------------------------------- ---------------------------------------- ---------- ----------ALLEN A E 1 2BLAKE A E 3 2JAMES A E 2 2MARTIN A I 2 2TURNER U E 2 2WARD A 2 1
WARD 에는 모음이 A 하나뿐이라 두 번째 모음 V2 가 NULL 이다.
BLAKE 의 첫 모음 A 는 세 번째 글자라 P1 이 3 이다.
문자열 리터럴로 함수의 세부 동작을 확인한다.
SELECT REGEXP_SUBSTR('02-1234-5678', '[0-9]+', 1, 2) AS A, REGEXP_SUBSTR('02-1234-5678', '\d+$') AS B, REGEXP_COUNT('02-1234-5678', '[[:digit:]]') AS C FROM DUAL;
A B C---- ---- ----------1234 5678 10
[0-9]+ 는 숫자가 이어진 덩어리 하나다. 두 번째 덩어리가 1234 다.
\d+$ 는 끝에 붙은 숫자 덩어리다. [[:digit:]] 은 숫자 한 글자라 10번 센다.
SELECT REGEXP_COUNT('banana', 'a') AS A, REGEXP_COUNT('banana', 'ana') AS B, REGEXP_INSTR('ABCABC', 'B', 1, 2) AS C, REGEXP_INSTR('ABCABC', 'B', 1, 1, 1) AS D FROM DUAL;
A B C D---------- ---------- ---------- ---------- 3 1 5 3
banana 에 ana 는 2-4번, 4-6번 자리에 겹쳐 있지만 1 이다. 한 번 일치한 글자 뒤에서 다음 검색을 시작하기 때문이다.
두 번째 B 는 5번째 글자다. 반환 옵션 1 을 주면 첫 B(2번) 다음 위치인 3 을 돌려준다.
그룹 번호를 주면 괄호로 묶은 부분만 꺼낸다.
SELECT REGEXP_SUBSTR('user@mail.com', '[^@]+') AS ID, REGEXP_SUBSTR('user@mail.com', '@(.+)$', 1, 1, NULL, 1) AS DOM FROM DUAL;
ID DOM---- --------user mail.com
[^@]+ 는 @ 가 아닌 글자의 덩어리라 앞쪽 user 가 나온다.
여섯 번째 인자 1 은 첫 번째 괄호 그룹을 뜻한다. 그룹 번호가 없으면 @ 까지 포함한 @mail.com 이 나온다.
MILLER 의 I 와 E 가 모두 바뀌었다. REGEXP_REPLACE 는 기본으로 모든 일치를 바꾼다.
바꿀 문자열 안의 \1, \2, \3 은 패턴에서 괄호로 잡은 부분이다. 날짜 순서를 뒤집고, 전화번호 가운데를 가린다.
SELECT REGEXP_REPLACE('2026-11-03', '(\d{4})-(\d{2})-(\d{2})', '\3/\2/\1') AS D, REGEXP_REPLACE('010-1234-5678', '(\d{3})-(\d{4})-(\d{4})', '\1-****-\3') AS P, REGEXP_REPLACE('a1b2c3', '\D') AS N FROM DUAL;
D P N---------- ------------- ---03/11/2026 010-****-5678 123
그룹 번호는 여는 괄호가 나온 순서다. 연도가 \1, 월이 \2, 일이 \3 이다.
\D 는 숫자가 아닌 글자다. 바꿀 문자열이 없으니 지워지고 숫자만 남는다. [^[:digit:]] 로 써도 결과가 같았다.
SELECT (SELECT COUNT(*) FROM EMP WHERE REGEXP_LIKE(ENAME, 'a')) AS C_DEFAULT, (SELECT COUNT(*) FROM EMP WHERE REGEXP_LIKE(ENAME, 'a', 'i')) AS C_I, (SELECT COUNT(*) FROM EMP WHERE REGEXP_LIKE(ENAME, 'a', 'ic')) AS C_IC FROM DUAL;
'ic' 처럼 서로 반대인 옵션을 함께 주면 마지막 c 가 적용되어 다시 0명이다. 'ci' 로 순서를 바꾸면 7명이었다.
'n' 과 'm' 은 줄바꿈이 든 문자열에서 차이가 난다. CHR(10) 이 줄바꿈 문자다.
SELECT REGEXP_COUNT('ab' || CHR(10) || 'ac', '^a') AS NO_M, REGEXP_COUNT('ab' || CHR(10) || 'ac', '^a', 1, 'm') AS M, CASE WHEN REGEXP_LIKE('a' || CHR(10) || 'b', 'a.b') THEN 'Y' ELSE 'N' END AS NO_N, CASE WHEN REGEXP_LIKE('a' || CHR(10) || 'b', 'a.b', 'n') THEN 'Y' ELSE 'N' END AS N FROM DUAL;
NO_M M N N---------- ---------- - - 1 2 N Y
기본에서 ^ 는 문자열 맨 앞 하나뿐이라 1 이다. 'm' 이면 둘째 줄 시작도 맞아 2 다.
세 번째 열이 NO_N, 네 번째 열이 N 이다. SQL*Plus 가 값 폭(1자)에 맞춰 열 머리를 잘랐다.
기본에서 . 은 줄바꿈과 맞지 않아 a.b 가 거짓이다. 'n' 을 주면 참이 된다.
내일은 테이블의 행을 넣고 고치고 지우는 DML(INSERT·UPDATE·DELETE·MERGE)을 다룬다.