WHERE 절은 행마다 조건을 따져 참인 행만 남깁니다. 조건은 비교 연산자와 BETWEEN·IN·LIKE·IS NULL로 쓰고, AND·OR·NOT으로 묶습니다.
테이블의 모든 행이 아니라 '월급이 450 이상인 사원'처럼 조건에 맞는 행만 보고 싶을 때가 많습니다. WHERE는 처리 순서(SELECT 문의 절이 처리되는 차례 — SELECT 문이 실행되는 순서 레슨에서 자세히)에서 FROM 바로 다음이라, 테이블의 행을 하나씩 거릅니다.
1비교 연산자와 SQL 연산자
=·>·>=·<·<=는 두 값을 견주는 비교 연산자입니다. 같지 않음은 Oracle에서 <>·!=·^= 셋으로 쓰고, SQL Server에는 ^=가 없습니다.
구간·목록·글자 틀·NULL은 SQL 연산자로 봅니다.
| 조건 | 뜻 | 남는 행 |
|---|---|---|
SAL BETWEEN 400 AND 450 | 400 이상 450 이하 | 박지호, 최유나 |
DEPTNO IN (10, 30) | 10 또는 30 | 김민준, 최유나 |
ENAME LIKE '_서%' | 둘째 글자가 '서' | 이서연 |
DEPTNO IS NULL | DEPTNO가 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 알 수 없음도 알 수 없음입니다.
| A | B | A AND B | A 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;
| EMPNO | ENAME | SAL | DEPTNO |
|---|---|---|---|
| 1002 | 이서연 | 380 | 20 |
| 1003 | 박지호 | 410 | 20 |
| 1004 | 최유나 | 450 | 30 |
| 1006 | 강도윤 | 470 | 20 |
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;
정답
이서연·박지호·최유나입니다.
| EMPNO | ENAME | SAL | DEPTNO |
|---|---|---|---|
| 1002 | 이서연 | 380 | 20 |
| 1003 | 박지호 | 410 | 20 |
| 1004 | 최유나 | 450 | 30 |
- 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;
정답
| EMPNO | ENAME | SAL | DEPTNO |
|---|---|---|---|
| 1002 | 이서연 | 380 | 20 |
| 1003 | 박지호 | 410 | 20 |
NOT은 AND보다 먼저 계산되어 바로 뒤의 SAL >= 450에만 걸립니다.
그래서 (SAL < 450) AND DEPTNO = 20이 되어 20번 부서에서 월급이 450보다 작은 두 사람이 남습니다.
아래처럼 괄호로 묶으면 뜻이 달라집니다.
NOT (SAL >= 450
AND DEPTNO = 20)