SQL에서의 패턴 검색은 LIKE 연산자에서 %와 ?를 이용하는 아주 간단한 형태이다. 값에 숫자가 있는지, 영문이 있는지 판단하려면 매우 힘들다. 하지만 정규 표현식을 사용한다면 전혀 어려울게 없어진다.
아래 내용은 mysql을 예로 설명하므로 다른 DBMS는 별도의 문서를 확인하자.
사용한 schema는 기본으로 제공되는 sakila를 사용한다.
MySql에서는 match_type이라는 내용이 있는데 이제까지 이야기했던 flag를 말한다.
match_type
의미
c
대/소문자를 구분한다.
i
대/소문자를 구분하지 않으며 기본 값이다.
m
multi line모드로 각 라인마다 시작 문자와 끝문자를 체크한다. 기본은 시작과 마지막 문장만을 대상으로 한다.
global에 대한 부분은 position과 occurence 옵션으로 처리한다.
REGEXP_LIKE()
문자열이 주어진 정규표현식에 부합하는지 체크하는 함수로 REGEXP, RLIKE와 동의어로 where 등 조건절에서 사용된다.
REGEXP_LIKE(source_char, expr[, match_type])
select district from address where regexp_like(district, '^[aeiou].*[aeiou]$');
select district from address where district regexp '^[aeiou].*[aeiou]$';
select district from address where district rlike '^[aeiou].*[aeiou]$';
// 총 48개의 행이 반환된다.
대소문자의 구분
mysql은 문자열 조회 시 기본적으로는 대소문자를 구분하지 않는다. 대소 문자에 대한 구분이 필요할 때는 binary 옵션을 사용한다. 또는 함수적의 파라미터인 match_type을 이용한다.
select district from address where regexp_like(district, '^[aeiou].*[aeiou]$', 'c');
select district from address where regexp_like(binary district, '^[aeiou].*[aeiou]$');
select district from address where binary district regexp '^[aeiou].*[aeiou]$';
select district from address where binary district rlike '^[aeiou].*[aeiou]$';
// 6개의 행이 반환된다.
REGEXP_INSTR()
regexp_instr()은 문자열 내에서 정규 표현식이 등장하는 위치 값을 반환한다.
REGEXP_INSTR(source_char, expr[, pos[, occurrence[, return_option[, match_type]]]])
- source_char: 점검 대상 문자열
- expr: 정규 표현식
- pos: 검색을 시작할 위치로 기본은 1
- occurrence: 몇 번째로 등장한 요소인가에 대한 옵션으로 기본은 1
- return_option: 0이면 matching이 시작한 곳, 1이면 matching이 끝난 다음 위치. 기본은 0
옵션들이 매우 다양한데 한번씩 실행해 보면 쉽게 그 의도를 파악할 수 있다.
select regexp_instr( 'Hello Regexp Sql', '[aeiou]'); -- 모음이 나온 위치
select regexp_instr( 'Hello Regexp Sql', '[aeiou]', 7); -- 7번째 문자(R)부터 모음이 나온 위치
select regexp_instr( 'Hello Regexp Sql', '[aeiou]', 7, 2); -- 7번째 문자(R)부터 두 번째모음이 나온 위치
select regexp_instr( 'Heeeello Regexp Sql', '[aeiou]+', 1, 1 , 1); -- 연속된 모음이 끝난 위치
select address, regexp_instr(address, '\\(La|\\(D') as 'loc'
from address
where regexp_instr(address, '\\(La|\\(D')>0;
'('를 그룹의 용도가 아닌 단순 괄호로 나타내기 위해서 정규 표현식 상 \를 이용해 escape 처리하고 이것을 sql 문장에서 다시 escape 하기 위해 \가 두 개 들어간 부분을 주의하자.
REGEXP_SUBSTR()
regexp_substr()은 source_char에서 정규표현식에 해당하는 문자열을 추출해서 리턴한다.
REGEXP_SUBSTR(source_char, expr[, pos[, occurrence[, match_type]]])
- source_char: 점검 대상 문자열
- expr: 정규 표현식
- pos: 검색을 시작할 위치로 기본은 1
- occurrence: 몇 번째로 등장한 요소인가에 대한 옵션으로 기본은 1
옵션을 음미하면서 사용해보자.
select regexp_substr( 'Hello Regexp Sql', '[aeiou]'); -- 첫 번재 모음
select regexp_substr( 'IronMan is Tony Stark', '[aeiou]', 9); -- 9번째 문자(i)부터 모음
select regexp_substr( 'Hello IronMan', '[aeiou]', 7, 2); -- 7번째 문자(I)부터 두 번째 모음
select regexp_substr( 'Heeeello Regexp Sql', '[aeiou]+', 1, 1); -- 1번째 문자부터 첫 번째 패턴
select email, regexp_substr(email, '(?<=@)[0-9a-zA-Z.]+$') domain from staff;
REGEXP_REPLACE()
REGEXP_REPLACE는 source_char에서 정규표현식에 해당하는 문자를 replace_string으로 대체한다.
REGEXP_REPLACE(source_char, expr, replace_string[, pos[, occurrence[, mtch_type]]])
- source_char: 점검 대상 문자열
- expr: 정규 표현식
- replace_string: 대체 문자
- pos: 검색을 시작할 위치로 기본은 1
- occurrence: 몇 번째로 등장한 요소인가에 대한 옵션으로 기본은 1
간단한 활용 예를 살펴보자.
-- b를 X로 대체한다.
SELECT REGEXP_REPLACE('a b c', 'b', 'X’);
-- 맨 처음부터 [a-z]가 한번 이상 나온 것의 3번째 것을 X로 대체한다.
SELECT REGEXP_REPLACE('abc def ghi', '[a-z]+', 'X', 1, 3);