정규표현식

정규 표현식 - SQL

  • -

이번 포스트에서는 SQL 함수에 사용되는 정규 표현식을 살펴보자.

 

Sql 함수에서의 정규 표현식

SQL에서의 패턴 검색은 LIKE 연산자에서 %와 ?를 이용하는 아주 간단한 형태이다. 값에 숫자가 있는지, 영문이 있는지 판단하려면 매우 힘들다. 하지만 정규 표현식을 사용한다면 전혀 어려울게 없어진다.

아래 내용은 mysql을 예로 설명하므로 다른 DBMS는 별도의 문서를 확인하자.

 

MySQL :: MySQL 8.0 Reference Manual :: 12.7.2 Regular Expressions

12.7.2 Regular Expressions Table 12.13 Regular Expression Functions and Operators Name Description NOT REGEXP Negation of REGEXP REGEXP Whether string matches regular expression REGEXP_INSTR() Starting index of substring matching regular expression REGE

dev.mysql.com

사용한 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); -- 연속된 모음이 끝난 위치

 

활용 예

address의 address에 (La, (D의 위치가 0보다 큰 자료를 출력하시오.

더보기
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번째 문자부터 첫 번째 패턴

 

활용예

staff에서 email의 domain 부분만 출력하시오.

더보기
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);

 

 

'정규표현식' 카테고리의 다른 글

\b와 \B의 차이  (0) 2021.01.04
정규 표현식 - JavaScript  (0) 2020.06.11
정규 표현식 - Java  (0) 2020.06.11
정규 표현식 - 유용한 표현들  (1) 2020.06.10
정규 표현식 - 메타문자  (0) 2020.06.10
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.