메뉴 건너뛰기

tnt_db

Oracle NOT IN 의 함정

운영자 2002.09.17 20:27 조회 수 : 2665 추천:17

NOT IN 이라는 연산자는 IN 연산자의 반대 개념으로 사용된다.
IN 이라 하면 지정된 값중 하나라도 비교되는값과 같은 값이 있으면
TRUE를 RETURN 하는 연산자이다.
다음예제를 보자.

SCOTT.EMP 를 다음과 같이 읽어보자.

SELECT * FROM   EMP;

EMPNO      ENAME      JOB       MGR        HIREDATE             SAL        COMM       DEPTNO    
---------- ---------- --------- ---------- -------------------- ---------- ---------- ----------
      7369 SMITH      CLERK           7902 80/12/17                    800                    20
      7499 ALLEN      SALESMAN        7698 81/02/20                   1600        300         30
      7521 WARD       SALESMAN        7698 81/02/22                   1250        500         30
      7566 JONES      MANAGER         7839 81/04/02                   2975                    20
      7654 MARTIN     SALESMAN        7698 81/09/28                   1250       1400         30
      7698 BLAKE      MANAGER         7839 81/05/01                   2850                    30
      7782 CLARK      MANAGER         7839 81/06/09                   2450                    10
      7788 SCOTT      ANALYST         7566 82/12/09                   3000                    20
      7839 KING       PRESIDENT            81/11/17                   5000                    10
      7844 TURNER     SALESMAN        7698 81/09/08                   1500          0         30
      7876 ADAMS      CLERK           7788 83/01/12                   1100                    20
      7900 JAMES      CLERK           7698 81/12/03                    950                    30
      7902 FORD       ANALYST         7566 81/12/03                   3000                    20
      7934 MILLER     CLERK           7782 82/01/23                   1300                    10
14 행이 선택되었습니다

이 중에서 MGR 이 7902 또는 7839 인 경우를 읽어오기위하여
다음과 같이 조건을 줄수 있을 것이다.

SELECT * FROM EMP
WHERE  MGR IN (7902,7839);

그러면 예상대로 4건의 RECORD가 끌려 나올것이다.

EMPNO      ENAME      JOB       MGR        HIREDATE             SAL        COMM       DEPTNO    
---------- ---------- --------- ---------- -------------------- ---------- ---------- ----------
      7369 SMITH      CLERK           7902 80/12/17                    800                    20
      7566 JONES      MANAGER         7839 81/04/02                   2975                    20
      7698 BLAKE      MANAGER         7839 81/05/01                   2850                    30
      7782 CLARK      MANAGER         7839 81/06/09                   2450                

그렇다면 다음과 같은 조건을 생각해보자.
1.MGR 이 NULL 또는 7839 인 경우
그리고...
2.MGR 이 NULL 또는 7839 모두에 속하지 않는경우.

1의 경우를 위하여
조건을 다음과 같이 주면 될까?.

SELECT * FROM EMP
WHERE  MGR IN (NULL,7839);

결과를 보자..

EMPNO      ENAME      JOB       MGR        HIREDATE             SAL        COMM       DEPTNO    
---------- ---------- --------- ---------- -------------------- ---------- ---------- ----------
      7566 JONES      MANAGER         7839 81/04/02                   2975                    20
      7698 BLAKE      MANAGER         7839 81/05/01                   2850                    30
      7782 CLARK      MANAGER         7839 81/06/09                   2450                    10
3 행이 선택되었습니다

MGR이 NULL인 경우는 빠졌다..
왜 빠졌을까?.
위의 조건을 다시쓰면 다음과 같이 된다.
WHERE MGR = NULL OR MGR = 7839;

이렇게 되면 MGR=NULL 이란 조건은 항상 FALSE 로 RETURN 된다.
왜?..
NULL 은 항상 IS NULL 또는 IS NOT NULL 로 비교되어야 하기 때문이다.
따라서 MGR=7839 인 경우만이 검색된다.

그렇다면 2 의 경우는 어떻겠는가??.
즉, MGR NOT IN (NULL,7839) 이 경우.
NULL 과 7839 를 제외한 나머지 경우인 10건을 모두 검색할까?
아니면 NULL을 빠뜨리고 7839인 경우만을 제외한 11건을 검색할까?.
둘다 아니다..
한건도 검색하지 못한다.
NOT IN 연산자에 NULL 이 포함되면 어떠한 경우에도 한건도 DATA를 검색하지 못한다.
왜 그럴까??.
생각을 해보자 NOT IN 또한 IN 의 경우와 마찬가지다.
단지 지정된 값의 어느값이든 한 값이라도 같은 값이 있으면 TRUE가  되므로
AND 로 묶이게 된다는 것이 차이다.
다시 풀어서 쓰면 다음과 같이 된다.
WHERE MGR <> NULL AND MGR <> 7839;
1 의 경우는 OR로 연결되어 둘 중 한 조건만을 만족하면 되지만
이경우는 두 조건을 모두 만족시켜야 하므로 모든 RECORD가 MGR<>NULL 조건에 위배된다.
따라서 검색되는 행은 어느경우에도 없게된다.
IN의 경우는 예상을 하지만 NOT IN의 경우는 예상을 못하고 당하는 경우가 많아서
조심해야된다.
위로