[MSSQL] #2 EXISTS, NOT EXISTS문 설명 및 사용법

이번 포스팅에서는 EXISTS 구문과 NOT EXISTS구문에 대해 알아보겠습니다.

 

 

EXISTS문은 IN문과 연계해서 살펴보면, 이해에 도움이 되실 거에요.

2021.03.25 - [DB/MS SQL] - [MSSQL] #1 IN, NOT IN 구문 설명 및 사용법(오류 케이스)

 

[MSSQL] #1 IN, NOT IN 구문 설명 및 사용법(오류 케이스)

안녕하세요~! 이번 포스팅은 일전에 살펴보았던 IN 구문과 NOT IN 구문에 대해 살펴볼게요. :-) (이와 연계해서 다음 포스팅은 EXISTS, NOT EXISTS문에 대해 포스팅해볼게요.) 2021.02.18 - [DB/MS SQL] - [MSSQL]..

woogie-db.tistory.com

 

EXISTS문?

EXISTS 구문은 문장 안에 데이터 존재유무를 판단할 수 있는 문법입니다.

또한, EXISTS는 INSERT나 UPDATE 구문 처리 시에 많이 활용할 수 있습니다.

 

 

한 테이블이 다른 테이블과 외래키(FK)와 같은 관계가 있을 때 유용하며,

EXISTS는 두 테이블 간의 결과를 어떤 값이 존재하는 지를 알고 싶은 경우 활용합니다.

   => 데이터가 존재하는지를 판단하는 것이 핵심입니다. :)

 

지금부터 예시 테이블을 통해  EXISTS문을 활용하는 방법에 대해 알아볼게요.🙌

 

 

<예시 테이블1>

  NO_COLOR NM_COLOR
1 1 RED
2 2 BLUE
3 NULL BLACK
4 3 NULL
5 4 WHITE
6 NULL NAVY

 

<예시 테이블2>

  NO_EMP NM_KOR
1 NULL 복태욱
2 1 NULL
3 2 박세인
4 NULL 권태준
5 3 이치원
6 4 NULL

 

SELECT문을 활용한 구문을 통해 살펴보면,

 

SELECT * FROM MA_COLOR C

WHERE EXISTS (SELECT E.NO_EMP FROM MA_EMP);

 

  NO_COLOR NM_COLOR
1 1 RED
2 2 BLUE
3 NULL BLACK
4 3 NULL
5 4 WHITE
6 NULL NAVY

 

해당 쿼리로 실행할 경우, 다음과 같은 결과가 나오게 됩니다.🤔

예상과는 다른 결과라고 생각할 수도 있는데, 구조를 같이 살펴볼까요~?

 

 

 

위의 쿼리를 기준으로 데이터베이스가 어떻게 동작하는지 한번 알아보겠습니다.

 

위에 IN구문 살펴본 게시글을 참고하면,

IN구문에서는 IN절 이후에 나오는 소괄호 내부의 서브쿼리에 대해서 먼저 접근하였습니다.

 

하지만!! EXISTS 구문에서는 IN구문과는 차이가 있습니다.

  • MA_COLOR 테이블에 접근해서 하나의 레코드를 가져옵니다.
  • EXISTS 이하의 서브쿼리를 실행하고 서브쿼리에 대한 결과가 '존재하는지'를 확인합니다.

예를 들면,

  • 가장 먼저 [ 1, RED ] 라는 레코드를 가져옵니다.
  • 해당 레코드에 대해 SELECT E.NO_EMP FROM MA_EMP E 쿼리를 통해 결과가 나오는지 확인합니다.
  • 이 때, 서브쿼리에 대해 어떠한 결과라도 존재하기만 한다면 참이 되어서 [ 1, RED ] 레코드가 출력됩니다.

중요한 점은 SELECT E.NO_EMP FROM MA_EMP E 쿼리는

MA_COLOR의 어떠한 레코드하고도 연관이 없이 항상 결과값을 가지는 쿼리에요. :)

따라서 MA_COLOR 테이블의 모든 레코드가 출력되는 것입니다!


그렇다면, 번호가 일치하는 결과를 출력하기 위해선 어떻게 구문을 활용해야할까요?!

 

SELECT * FROM MA_COLOR C

WHERE EXISTS (SELECT E.NO_EMP FROM MA_EMP E WHERE E.NO_EMP = C.NO_COLOR)

 

  NO_COLOR NM_COLOR
1 1 RED
2 2 BLUE
4 3 NULL
5 4 WHITE

이렇게 나온 결과는 사실 IN 구문과 같은 결과를 출력합니다.

하지만!! 내부적으로 쿼리가 동작하는 방식은 다르다는 것에 주의하시길 바랍니다.

이러한 내부 로직에 따라서 성능 차이가 크게 발생하기 때문에 알아두도록 합시다.😃


다음은 NOT EXISTS 구문에 대해 살펴보겠습니다.

NOT EXISTS문?

NOT EXISTS에 대해서도 위에서 살펴본 EXISTS문에 대한 이해를 하셨다면 큰 어려움이 없이 활용하실 수 있을 거에요.

NOT IN과는 차이가 있겠죠~?

 

 

SELECT * FROM MA_COLOR C

WHERE NOT EXISTS (SELECT E.NO_EMP FROM MA_EMP E WHERE E.NO_EMP = C.NO_COLOR)

 

  NO_COLOR NM_COLOR
1 NULL BLACK
2 NULL NAVY

 

앞의 NOT IN 구문에서 살펴보았을 경우에는

NO_COLOR 값이 NULL인 레코드는 출력되지 않았습니다.

(위 링크 게시글 참조)

 

그 이유를 다시  한번 생각해보면,

IN 구문은 요소간의 비교 연산으로 레코드를 출력하는데 NULL 값에 대한 비교연산은 항상 UNKNOWN을 반환하기 때문이었습니다.

 

하지만!! 위에서 살펴보았을 때 EXISTS 구문은 IN과는 다르게 동작하는 걸 확인할 수 있었죠?

위 쿼리를 기준으로 살펴보겠습니다.

  • MA_COLOR 테이블에서 레코드를 가져옵니다.
  • 해당 레코드의 NO_COLOR 값을 NOT EXISTS 이하의 서브쿼리에 전달하여 해당 서브쿼리에서 값이 존재하는지를 확인합니다.
  • NOT EXISTS 구문이기에 해당 서브쿼리의 값이 존재하지 않으면 해당 레코드를 출력합니다.
    ⁕EXISTS 구문이었다면 값이 존재할 때 해당 레코드를 출력합니다.

NULL이 출력되는 과정을 자세하게 알아보게 되면,

[ NULL, BLACK ] 레코드를 예로 우선 살펴볼게요.

 

NO_COLOR = NULL 입니다.

따라서 NOT EXISTS 이하의 쿼리를 확인해보면 다음과 같을 것 입니다.

 

SELECT E.NO_EMP FROM MA_EMP E WHERE E.NO_EMP = NULL

 

이 때, NOT IN에서 알아본 것과 동일하게 NULL에 대한 비교연산은 항상 UNKNOWN 값을 반환합니다.

따라서 해당 쿼리의 결과가 존재하지 않게 되고,  [ NULL, BLACK ] 레코드가 출력되는 것입니다.

 

IN구문과 EXISTS 구문은 많이 헷갈리기도 하고, 동일한 결과값에 대한 구문이 달라지기도 합니다.

따라서 두 구문의 차이를 잘 이해하시면 좋을 것 같아요~!

 

저도 다시 공부하면서 정리를 한번 더 했습니다!! 화이팅👏

 

 

댓글

Designed by JB FACTORY