REGEXP 함수는 정규 표현식을 사용하여 문자열을 처리하는 SQL 함수이다. 특정 패턴을 기반으로 텍스트를 검색하건, 데이터를 검증하고, 문자열을 치환하는데 활용된다.
WHERE 절에서 패턴 일치 여부 확인
-- 기본 사용법
SELECT * FROM employees
WHERE REGEXP_LIKE(email, '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}$');
-- 대소문자 무시 옵션 ('i')
SELECT * FROM employees
WHERE REGEXP_LIKE(name, '^kim', 'i');
-- 이름이 'A'로 시작하는 직원
SELECT * FROM employees
WHERE REGEXP_LIKE(first_name, '^A');
구문: REGEXP_LIKE(source_string, pattern [, match_parameter])
match_parameter 옵션:
'i': 대소문자 무시'c': 대소문자 구분 (기본값)'n': .이 개행 문자도 매칭'm': 다중 라인 모드패턴과 일치하는 부분을 다른 문자열로 교체
-- 전화번호에서 특수문자 제거
SELECT
phone,
REGEXP_REPLACE(phone, '[^0-9]', '') AS clean_phone
FROM contacts;
-- 여러 공백을 하나로
SELECT REGEXP_REPLACE('Hello World', ' +', ' ') AS result FROM DUAL;
-- 결과: 'Hello World'
-- 이메일 마스킹 (앞 3자리만 보이기)
SELECT
email,
REGEXP_REPLACE(email, '^(.{3})(.*)(@.*)$', '\1***\3') AS masked_email
FROM users;
구문: REGEXP_REPLACE(source_string, pattern [, replace_string [, position [, occurrence [, match_parameter]]]])
패턴과 일치하는 부분 문자열 추출
-- 이메일에서 사용자명 추출
SELECT
email,
REGEXP_SUBSTR(email, '^[^@]+') AS username
FROM users;
-- 이메일에서 도메인 추출
SELECT
email,
REGEXP_SUBSTR(email, '@(.+)$', 1, 1, NULL, 1) AS domain
FROM users;
-- 문자열에서 첫 번째 숫자 추출
SELECT REGEXP_SUBSTR('abc123def456', '[0-9]+') AS first_number FROM DUAL;
-- 결과: '123'
-- 문자열에서 두 번째 숫자 추출
SELECT REGEXP_SUBSTR('abc123def456', '[0-9]+', 1, 2) AS second_number FROM DUAL;
-- 결과: '456'
구문: REGEXP_SUBSTR(source_string, pattern [, position [, occurrence [, match_parameter [, subexpression]]]])
패턴이 나타나는 위치 반환
-- 첫 번째 숫자의 위치 찾기
SELECT REGEXP_INSTR('abc123def', '[0-9]') AS position FROM DUAL;
-- 결과: 4
-- 이메일에서 @ 위치 찾기
SELECT
email,
REGEXP_INSTR(email, '@') AS at_position
FROM users;
-- 두 번째 공백의 위치
SELECT REGEXP_INSTR('Hello World Test', ' ', 1, 2) AS position FROM DUAL;
-- 결과: 12
-- 패턴의 끝 위치 반환 (return_option = 1)
SELECT REGEXP_INSTR('abc123def', '[0-9]+', 1, 1, 1) AS end_position FROM DUAL;
-- 결과: 7
구문: REGEXP_INSTR(source_string, pattern [, position [, occurrence [, return_option [, match_parameter [, subexpression]]]]])
패턴이 나타나는 횟수 세기
-- 문자열에서 'o' 개수
SELECT REGEXP_COUNT('hello world', 'o') AS count FROM DUAL;
-- 결과: 2
-- 문자열에서 숫자 개수
SELECT REGEXP_COUNT('abc123def456', '[0-9]') AS count FROM DUAL;
-- 결과: 6
-- 이메일에서 점(.) 개수
SELECT
email,
REGEXP_COUNT(email, '\.') AS dot_count
FROM users;
구문: REGEXP_COUNT(source_string, pattern [, position [, match_parameter]])
-- 1. 이메일 검증
WHERE REGEXP_LIKE(email, '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$')
-- 2. 전화번호 (010-1234-5678)
WHERE REGEXP_LIKE(phone, '^01[0-9]-[0-9]{4}-[0-9]{4}$')
-- 3. 휴대폰 (010으로 시작하는 11자리)
WHERE REGEXP_LIKE(mobile, '^010[0-9]{8}$')
-- 4. 숫자만
WHERE REGEXP_LIKE(code, '^[0-9]+$')
-- 5. 영문자만
WHERE REGEXP_LIKE(name, '^[A-Za-z]+$')
-- 6. 영문+숫자
WHERE REGEXP_LIKE(username, '^[A-Za-z0-9]+$')
-- 7. 한글만 (Unicode 범위)
WHERE REGEXP_LIKE(name, '^[가-힣]+$')
-- 8. 주민등록번호 (6자리-7자리)
WHERE REGEXP_LIKE(ssn, '^[0-9]{6}-[0-9]{7}$')
-- 9. 우편번호 (5자리)
WHERE REGEXP_LIKE(zipcode, '^[0-9]{5}$')
-- 10. IP 주소
WHERE REGEXP_LIKE(ip, '^([0-9]{1,3}\.){3}[0-9]{1,3}$')
-- 11. URL
WHERE REGEXP_LIKE(url, '^https?://[A-Za-z0-9.-]+\.[A-Za-z]{2,}')
-- 12. 비밀번호 (영문+숫자+특수문자, 8-20자)
WHERE REGEXP_LIKE(password, '^(?=.*[A-Za-z])(?=.*[0-9])(?=.*[@$!%*#?&])[A-Za-z0-9@$!%*#?&]{8,20}$')
SELECT employee_id, email
FROM employees
WHERE REGEXP_LIKE(email, '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$');
-- 010-1234-5678 → 01012345678
SELECT
phone,
REGEXP_REPLACE(phone, '-', '') AS formatted_phone
FROM contacts;
-- 01012345678 → 010-1234-5678
SELECT
phone,
REGEXP_REPLACE(phone, '([0-9]{3})([0-9]{4})([0-9]{4})', '\1-\2-\3') AS formatted_phone
FROM contacts
WHERE REGEXP_LIKE(phone, '^[0-9]{11}$');
SELECT
REGEXP_SUBSTR(email, '@(.+)$', 1, 1, NULL, 1) AS domain,
COUNT(*) AS user_count
FROM users
GROUP BY REGEXP_SUBSTR(email, '@(.+)$', 1, 1, NULL, 1)
ORDER BY user_count DESC;
-- 검증
SELECT *
FROM members
WHERE REGEXP_LIKE(ssn, '^[0-9]{6}-[1-4][0-9]{6}$');
-- 마스킹 (뒷자리 숨김)
SELECT
name,
REGEXP_REPLACE(ssn, '(-[0-9]{7})$', '-*******') AS masked_ssn
FROM members;
-- 제품 코드: 영문 2자 + 숫자 4자 (예: AB1234)
SELECT product_name, product_code
FROM products
WHERE REGEXP_LIKE(product_code, '^[A-Z]{2}[0-9]{4}$');
SELECT
description,
REGEXP_REPLACE(description, '[^0-9]', '') AS numbers_only
FROM products;
SELECT
address,
REGEXP_REPLACE(address, '( ){2,}', ' ') AS clean_address
FROM locations;
SELECT
url,
REGEXP_REPLACE(url, '^https?://', '') AS url_without_protocol
FROM websites;
CREATE INDEX idx_email_domain ON users(REGEXP_SUBSTR(email, '@(.+)$', 1, 1, NULL, 1));
-- 성능 개선: LIKE로 먼저 필터링
SELECT *
FROM users
WHERE email LIKE '%@gmail.com'
AND REGEXP_LIKE(email, '^[A-Za-z0-9._%+-]+@gmail\.com$');
-- 나쁜 예
WHERE REGEXP_LIKE(column, '매우_복잡한_정규식_패턴')
-- 좋은 예
WHERE column LIKE '%keyword%'
AND REGEXP_LIKE(column, '간단한_패턴')
정규표현식은 강력하지만 성능에 영향을 줄 수 있으므로, 대용량 데이터에서는 신중하게 사용해야 합니다!