DB/SQL - Oracle

[SQL] where 조건절 - Like(패턴) 방식 파헤치기 + 정규 표현식

생각많은 프로그래머 2024. 2. 3. 00:10

select문으로 데이터 조회 시

특히 특정 문자열을 포함한 값을 찾고자 할 때

Like를 자주 활용하게 된다. 

 

예를 들어 거주지 주소를 입력하는 address 컬럼명의 값은

서울시, 서울특별시, 수원시, 경기도 수원시, 등등 

같은 지역을 의미함에도 다른 값으로 저장된 경우가 있는데

이런 모든 경우를 포괄하면서 최대한 누락되지 않도록

조회를 하기 위해서 Like가 매우 유용하게 쓰일 수 있다.

 

예시) 컬럼이 address인 경우, 입력값에서 '서울'로 시작되는 문자열인 튜플만 조회 

SELECT * 
FROM member
WHERE address LIKE '서울%';

 

 

또한 웹 서비스 중 검색 기능을 구현하고자 할 때

사용자가 검색창에 입력한 검색어를 기준으로,

해당 키워드가 포함된 게시글의 제목이나 내용을

조회할 경우에도 Like가 유용하게 사용될 수 있다.

 

이번에는 Like에 대해 가능한 상세히 다뤄보며

이 글 하나로 Like 활용법을 익혀보고자 한다.

 

 

LIKE 는 단독으로 사용되지 않고,

위의 예시처럼 '%'와 같이 와일드 문자*와 함께 사용된다.

 

와일드 문자?

더보기

와일드 문자란, 데이터베이스에서 특정 명령어로

명령을 내릴 때, 여러 대상을 한꺼번에 지정할 목적으로

사용하는 기호를 말한다. 

 

이러한 와일드 문자를 사용하면 패턴을 더 세밀하게 제어할 수 있고

원하는 데이터를 세밀한 조건에 맞게 매칭하여 검색하는 데 큰 도움이 된다.

 

Like와 같이 사용되는 와일드 문자는 다음과 같다.

와일드 문자 설명 예시
+ 문자열을 연결 LIKE '축구' + '감독'
설명 : '축구 감독'에 해당하는 문자열 검색
% 0개 이상의 문자열과 일치 LIKE '키워드%'
설명 : 키워드로 시작하는 문자열 검색
[  ] 1개의 문자와 일치 LIKE '[0-8]%'
설명 : 0-8 사이 숫자로 시작하는 문자열 검색
[ ^ ] 1개의 문자와 불일치 LIKE '[^0-8]%' 
설명 : 0-8 사이 숫자로 시작하지 않는 문자열 검색
_ 특정 위치의 1개의 문자와 일치 LIKE '_동%' 
설명 : 첫 문자에는 아무 문자나 들어갈 수 있고,
두 번째 위치에 '동'이 들어가는 문자열 검색

 

중요한 포인트는 %와 _를 구분하는 것과 

두 와일드 문자의 위치를 어디에 두는 지인데,

 

 %에는 문자 길이가 한 글자 이상의 모든 문자열이 
들어갈 수 있는 반면, _의 경우에는 딱 한 글자만 가능하다.


%와 _는 키워드의 앞과 뒤,  혹은 중간에 올 수 있고,
 

이 위치에 따라 SELECT으로 조회한 결과값이 다르게 나올 수 있다.

또한 %와 _는 함께 쓸 수도 있다. 예) %키워드_

 

Like에 반대되는 연산자는 NOT LIKE 인 점도 기억해두자.

 

 

이제 예시와 함께 LIKE의 문법에 대해 좀 더 상세히 살펴보자.

-- 제품 테이블 products 생성
CREATE TABLE products (
    id INT PRIMARY KEY,
    name VARCHAR(100),
    description VARCHAR(255)
);

-- 데이터 삽입
INSERT ALL
INTO products (id, name, description) VALUES (1, 'Apple', 'Fresh red apple')
INTO products (id, name, description) VALUES (2, 'Banana', 'Ripe yellow banana')
INTO products (id, name, description) VALUES (3, 'Orange', 'Juicy orange citrus fruit')
INTO products (id, name, description) VALUES (4, 'Strawberry', 'Sweet red strawberry')
INTO products (id, name, description) VALUES (5, 'Pineapple', 'Fresh pineapple fruit')
SELECT 1 FROM DUAL;

 

테이블 products 생성 후 데이터 삽입

 

예시 1 

 

name컬럼에서 값이 e로 끝나는 모든 튜플을 조회했다.

 

예시 2

 

name컬럼에서 값이 P로 시작하고 중간에 n이 오는 모든 튜플을 조회했다.

예시 3

 

name컬럼에서 값이 S로 시작하고 y로 끝나는 모든 튜플을 조회했다.

예시 4

 

name컬럼에서 값이 O로 시작하고, 두 번째 자리에 랜덤으로 한 문자가 

온 다음 이어서 세 번째 자리에 a가 오는 모든 튜플을 조회했다.

 

WHERE절에는 OR이나 AND 도 사용할 수 있는데,

LIKE  연산자를 쓸 때 적용해볼 수 있다.

예시 5 : OR

 

name컬럼에  a 혹은 e 가 포함된 모든 튜플을 조회했다. 

둘 중 하나만 있어도 조건에 해당한다.

예시 6 : AND

name컬럼에  a 와 e 가 포함된 모든 튜플을 조회했다. 

둘 모두 있어야 조건에 해당하므로 id가 1과 2인 튜플은 조회되지 않았다.

 

한 가지 주의할 점이 있는데, 

바로 Like 연산자는 대문자와 소문자를 다르게 식별한다는 점이다. 

따라서 'apple'과 'Apple'은 다른 값으로 인식된다.

예시 5에서 보면 id가 1인 튜플의 name컬럼 값은 Apple이다.

만약 a와 A를 같은 문자로 인식했다면 분명 예시 6에서의 

Where 조건에 id가 1번인 튜플도 조회가 되었어야 할 것이다. 

 

예시 7

 

숫자 0에서 9사이의 문자열로 시작하는 값을 가진 

name컬럼의 값은 없기 때문에

위와 같이 아무런 튜플도 조회되지 않았다.

 

그렇다면 ^를 추가하면  모든 튜플이 조회될까?

0~9 사이의 숫자가 아닌 문자 하나와

이어서 %자리에 아무런 문자나 올 수 있으므로

사실상 모든 튜플이 조회되지 않을까? 

 

하지만, 결과는 아무런 튜플이 조회되지 않았다.

 

그 이유는 LIKE와 정규 표현식 인 [...]를 함께 사용할 수 없기 때문이다.

 

정규 표현식이란?

더보기

정규 표현식(Regular Expression)은 문자열의 패턴을 정의하는데

사용되는 형식 언어를 말한다. 정규 표현식을 사용하면

특정 패턴의 문자열을 검색하거나 변환하는 등의 작업을 수행할 수 있다.

 

정규 표현식은 다양한 문자 및 메타 문자로 구성된다.

다음은 일반적으로 사용되는 메타 문자목록의 일부이다.

  1. . (마침표) : 어떤 한 문자와 일치하는 경우
  2. * : 바로 앞의 문자가 0개 이상 나타나는 경우
  3. + : 바로 앞의 문자가 1개 이상 나타나는 경우
  4. ? : 바로 앞의 문자가 0개 또는 1개 나타나는 경우
  5. [ ] : 괄호 안의 문자 중 하나와 일치하는 경우
  6. ^ : 문자열이나 라인의 시작을 나타내는 경우
  7. $ : 문자열이나 라인의 끝을 나타내는 경우
  8. \ : 이스케이프 문자

이러한 메타 문자를 조합하여 복잡한 패턴을 표현할 수 있다.

정규 표현식은 다양한 프로그래밍 언어나 텍스트 에디터에서 지원되며,

문자열 처리나 검색 작업 등에 널리 사용된다.

 

 

그러면 정규 표현식과 함께 사용하려면 어떻게 수정해야 할까?

바로 LIKE 대신 REGEXP_LIKE를 쓰면 된다.

아래의 예시대로면, 의도했던 대로

0~9 사이의 숫자로 시작하지 않는 모든 문자열을 조회하게 되고,

결과적으로 모든 튜플이 조회된다.

 

 

예시 8

 

참고) 예시 5

SELECT * 
FROM products 
WHERE name LIKE '%a%' OR name LIKE '%e%';

 

예시 5와 같이 name 컬럼의 값에

문자 a나 e가 포함된 행을 조회하고자 한다면, 

아래와 같이 REGEXP_LIKE와 정규 표현식으로 조회할 수 있다.

 

참고로 여기서 1번 튜플이 조회된 이유는 A때문이 아니라 

e가 포함되어 있기 때문이다.

(문자 a 또는 e가 포함된 경우이므로)

기본적으로 대소문자를 구분하기 때문에

만약 [ae]대신 [Ae]로 조회했다면 2번 튜플이 조회되지 않게 된다.

 

 

*** TIP : 대소문자를 무시하고 검색하려면

 

1. 데이터베이스의 설정을 변경하거나,

 

2. LOWER() 또는 UPPER() 함수를 사용하여

대문자 또는 소문자로 변환한 후 비교해야 한다.

 

3. 혹은 아래와 같은 대소문자 무시 옵션을 추가하는 방법으로도 가능하다.

REGEXP_LIKE() 함수에 대소문자를 무시하는 옵션을 추가해야 한다.

아래 쿼리에서 'i'는 대소문자를 무시하는 옵션이다.

SELECT * FROM products WHERE REGEXP_LIKE(name, '[Ae]', 'i');

 

이렇게 조회하면 모든 튜플이 조회된다.

모든 튜플의 name컬럼의 값에

a, A, e, E 중 하나가 포함되어 있기 때문이다.