본문으로 건너뛰기

WHERE 절

SQLD 목차SQL 기본레슨 16 / 35

목차

WHERE 절은 행마다 조건을 따져 참인 행만 남깁니다. 조건은 비교 연산자와 BETWEEN·IN·LIKE·IS NULL로 쓰고, AND·OR·NOT으로 묶습니다.

테이블의 모든 행이 아니라 '월급이 450 이상인 사원'처럼 조건에 맞는 행만 보고 싶을 때가 많습니다. WHERE는 처리 순서(SELECT 문의 절이 처리되는 차례 — SELECT 문이 실행되는 순서 레슨에서 자세히)에서 FROM 바로 다음이라, 테이블의 행을 하나씩 거릅니다.

7단계 중 1단계. WHERE는 행마다 조건을 따져 참인 행만 남기고, SAL >= 450에는 450도 들어갑니다.

1비교 연산자와 SQL 연산자

=·>·>=·<·<=는 두 값을 견주는 비교 연산자입니다. 같지 않음은 Oracle에서 <>·!=·^= 셋으로 쓰고, SQL Server에는 ^=가 없습니다. 구간·목록·글자 틀·NULL은 SQL 연산자로 봅니다.

조건뜻남는 행
SAL BETWEEN 400 AND 450400 이상 450 이하박지호, 최유나
DEPTNO IN (10, 30)10 또는 30김민준, 최유나
ENAME LIKE '_서%'둘째 글자가 '서'이서연
DEPTNO IS NULLDEPTNO가 NULL정하늘

BETWEEN은 400 <= SAL AND SAL <= 450⁠처럼 양 끝을 포함하고, 작은 값을 앞에 써야 합니다. 거꾸로 쓴 BETWEEN 450 AND 400은 450 <= SAL AND SAL <= 400⁠이 되어 오류 없이 0행입니다. IN은 DEPTNO = 10 OR DEPTNO = 30⁠처럼 =를 OR로 이은 것입니다. LIKE의 글자 틀(패턴)에서 _는 꼭 한 글자, %는 0글자 이상이라 '이서연%'는 이서연도 찾습니다. NOT을 붙이면 반대라서 NOT BETWEEN 400 AND 450⁠은 양 끝인 400과 450도 뺍니다.

고정 길이 문자형 CHAR끼리는 짧은 쪽 뒤에 공백을 채워 견주고, 가변 길이 문자형 VARCHAR2가 끼면 공백도 글자로 봅니다. CHAR(5) 열의 'AB'는 = 'AB '(공백 둘)로도 찾히지만, VARCHAR2 열의 'AB'는 찾히지 않습니다.

2NULL과의 비교

NULL과 견준 조건은 참도 거짓도 아닌 '알 수 없음(UNKNOWN)'이고, WHERE는 참인 행만 남깁니다. 그래서 DEPTNO = NULL은 오류 없이 0행이고, 20번 부서가 아닌 정하늘도 DEPTNO <> 20에서 빠집니다. NOT IN은 <>를 AND로 이은 것이라, 목록에 NULL이 있으면 늘 알 수 없음이 끼어 0행입니다. LIKE '%'도 NULL은 찾지 못합니다.

3AND·OR·NOT과 우선순위

AND는 둘 다 참이어야, OR는 하나만 참이어도 참입니다. 알 수 없음이 끼면 아래처럼 되고, NOT 알 수 없음도 알 수 없음입니다.

ABA AND BA OR B
참알 수 없음알 수 없음참
거짓알 수 없음거짓알 수 없음
알 수 없음알 수 없음알 수 없음알 수 없음

정하늘의 SAL < 400(참)과 DEPTNO = 20(알 수 없음)이 표의 첫 줄입니다.

섞어 쓴 조건은 시험 기준으로 괄호 → NOT → 비교·SQL 연산자 → AND → OR 차례로 계산합니다. Oracle은 비교 연산자를 NOT보다 먼저 계산하지만, NOT은 참·거짓에만 붙으므로 NOT SAL >= 450은 어느 쪽이든 NOT (SAL >= 450)입니다.

예제

괄호 없이 AND와 OR를 섞은 조건입니다.

SELECT EMPNO,
  ENAME,
  SAL,
  DEPTNO
FROM EMP
WHERE DEPTNO = 20
  OR DEPTNO = 30
  AND SAL >= 450
ORDER BY EMPNO;
EMPNOENAMESALDEPTNO
1002이서연38020
1003박지호41020
1004최유나45030
1006강도윤47020

AND를 먼저 묶어 아래처럼 계산하므로 20번 부서 사원은 월급과 상관없이 남습니다.

DEPTNO = 20
  OR (DEPTNO = 30
    AND SAL >= 450)

OR를 괄호로 먼저 묶으면 최유나·강도윤 2행입니다.

ESCAPE는 %·_를 글자 그대로 찾게 하는 탈출 문자를 정합니다. EMP에는 _가 든 값이 없어 CODES 테이블을 따로 만듭니다.

CREATE TABLE CODES (
  CODE VARCHAR2(10)
);
INSERT INTO CODES
VALUES ('A_1');
INSERT INTO CODES
VALUES ('AB1');
SELECT CODE
FROM CODES
WHERE CODE LIKE 'A\_%'
    ESCAPE '\'
ORDER BY CODE;
CODE
A_1

\ 바로 뒤의 _는 아무 글자 하나가 아니라 글자 _입니다. ESCAPE 없이 LIKE 'A_%'로 쓰면 AB1도 나옵니다.

시험 포인트

  • BETWEEN a AND b는 양 끝을 포함합니다. BETWEEN 450 AND 400은 오류 없이 0행입니다.
  • _는 꼭 한 글자, %는 0글자 이상이고, LIKE '%'도 NULL은 못 찾습니다.
  • = NULL은 오류 없이 0행입니다. NULL은 IS NULL·IS NOT NULL로 가립니다.
  • NOT IN 목록에 NULL이 있으면 0행입니다.
  • 참 AND 알 수 없음은 빠지고, 참 OR 알 수 없음은 남습니다.
  • 우선순위는 괄호 → NOT → 비교·SQL 연산자 → AND → OR입니다.
  • 같지 않음은 Oracle에서 <>·!=·^=이고, SQL Server에는 ^=가 없습니다.
  • CHAR끼리는 공백을 채워 견주고, VARCHAR2가 끼면 공백도 글자로 봅니다.

확인 문제

1. 다음 쿼리의 결과로 나오는 사원은 누구일까요?

SELECT EMPNO,
  ENAME,
  SAL,
  DEPTNO
FROM EMP
WHERE SAL BETWEEN 380 AND 450
  AND DEPTNO IN (20, 30)
ORDER BY EMPNO;
정답

이서연·박지호·최유나입니다.

EMPNOENAMESALDEPTNO
1002이서연38020
1003박지호41020
1004최유나45030
  • 380·450은 BETWEEN의 양 끝값이라 듭니다.
  • 강도윤(470)은 BETWEEN에서, 정하늘(300)은 BETWEEN과 IN 모두에서 빠집니다.

2. 다음 두 조건으로 EMP를 거르면 각각 몇 행이 나올까요?

  • ① WHERE DEPTNO NOT IN (10, 20)
  • ② WHERE DEPTNO NOT IN (10, 20, NULL)
정답

①은 1행(최유나), ②는 0행입니다. ①에서 정하늘은 NULL <> 10부터 알 수 없음이라 빠집니다. ②는 최유나도 30 <> NULL이 알 수 없음이라, AND로 묶으면 참인 행이 없습니다.

3. 다음 쿼리의 결과는 무엇일까요? NOT이 어디까지 걸리는지 보세요.

SELECT EMPNO,
  ENAME,
  SAL,
  DEPTNO
FROM EMP
WHERE NOT SAL >= 450
  AND DEPTNO = 20
ORDER BY EMPNO;
정답
EMPNOENAMESALDEPTNO
1002이서연38020
1003박지호41020

NOT은 AND보다 먼저 계산되어 바로 뒤의 SAL >= 450에만 걸립니다. 그래서 (SAL < 450) AND DEPTNO = 20⁠이 되어 20번 부서에서 월급이 450보다 작은 두 사람이 남습니다. 아래처럼 괄호로 묶으면 뜻이 달라집니다.

NOT (SAL >= 450
    AND DEPTNO = 20)

끝까지 내려오면 저절로 표시됩니다. 이 기기에만 저장합니다.

SQLD 목차로