기초부터 시작하는 코딩

오라클SQL) EXISTS와 NOT EXISTS에 대해 알아보자

kebab00 2024. 10. 24. 09:53

728x90

먼저 EXISTS 와  NOT EXISTS가 무엇인지 살펴보자 

EXISTS는 SQL에서 EXISTS(서브쿼리) 식으로 사용되며 서브쿼리의 값이 있을 때 true를, 없을 때 false를 반환한다.

NOT EXISTS는 EXISTS과는 반대로 NOT EXISTS(서브쿼리) 식으로 사용되며 서브쿼리의 값이 있을 때 false를, 없을 때 true를 반환한다.

 EXISTS(SELECT * FROM TB_TEST WHERE 1=1)
 = true
 
 NOT EXISTS(SELECT * FROM TB_TEST WHERE 1=1)
 = false


이런 식으로 반환이 된다는 것이다.

이걸 조건문에 사용해서 다른 곳에서 가져온 데이터와 기존에 저장되어 있는 데이터를 비교해 새로운 값만 INSERT를 할 수 있게 해준다.

예제 1 INSERT

예를 들면 T_TEST 라는 테이블이 있다고 가정해보자

TEST_NO TEST_NM
1 TSET01
2 TSET02

그 안에 이런 값이 있다면

INSERT INTO T_TEST
(TEST_NO, TEST_NM)
SELECT 
  TEST_NO
  , TEST_NM
FROM 
(SELECT 1 AS TEST_NO, 'TEST01' AS TEST_NM FROM DUAL
UNION ALL SELECT 3 AS TEST_NO, 'TEST03' AS TEST_NM FROM DUAL) T
WHERE NOT EXISTS(SELECT TEST_NO FROM T_TEST WHERE TEST_NO = T.TEST_NO);

조금 복잡하지만 이런 SQL문을 실행하게 된다면

TEST_NO 가 1인 값은 이미 테이블에 있으므로 TEST_NO가 3 인 것만 INSERT하게된다. 

코드를 잠깐 살펴보자면 

(SELECT 1 AS TEST_NO, 'TEST01' AS TEST_NM FROM DUAL
UNION ALL SELECT 3 AS TEST_NO, 'TEST03' AS TEST_NM FROM DUAL)

이부분은 내가 받아오는 데이터를 넣는 부분이다.

만약 itemList 라는 배열에 TEST_NO와 TEST_NM을 각각 testNo와 testNm으로 받아온다고 생각해보자

{
  itemList : [
    {
      testNo : 1,
      testNm : "test01"
    },
    {
      testNo : 2,
      testNm : "test02"
    },
    {
      testNo : 3,
      testNm : "test03"
    },
  ]
}

 이런 식으로 들어온 들어온 데이터가 xml에서 아래의 코드를 만나면  

(
<foreach item="item" collection="itemList" separator="UNION ALL" >
 SELECT #{item.testNo} AS TEST_NO, #{item.testNm} AS TEST_NM FROM DUAL
</foreach>
)
(SELECT 1 AS TEST_NO, 'TEST01' AS TEST_NM FROM DUAL
UNION ALL SELECT 2 AS TEST_NO, 'TEST02' AS TEST_NM FROM DUAL
UNION ALL SELECT 3 AS TEST_NO, 'TEST03' AS TEST_NM FROM DUAL)

사실상 위의 코드로 변하는 것이다.

위의 FROM DUAL는 임의의 데이터 혹은 계산결과를 출력할 때 쓰인다.

그다음 밖에 있는 SELECT 문을 살펴보면 

SELECT 
  TEST_NO
  , TEST_NM
FROM 
(SELECT 1 AS TEST_NO, 'TEST01' AS TEST_NM FROM DUAL
UNION ALL SELECT 3 AS TEST_NO, 'TEST03' AS TEST_NM FROM DUAL) T
WHERE NOT EXISTS(SELECT TEST_NO FROM T_TEST WHERE TEST_NO = T.TEST_NO);

이라고 되어 있는데 

SELECT 
  TEST_NO
  , TEST_NM
FROM 
(SELECT 1 AS TEST_NO, 'TEST01' AS TEST_NM FROM DUAL) T
WHERE NOT EXISTS(SELECT TEST_NO FROM T_TEST WHERE TEST_NO = T.TEST_NO);

UNION ALL 를 지우고 보면 조금 더 쉽다.

FROM DUAL 로 만든

TEST_NO TEST_NM
1 TSET01

이라는 테이블의 TEST_NO와  T_TEST의 TEST_NO를 비교해서 DUAL 테이블에 값이 없는 것들만 뽑아 INSERT 하게 되는 것이다.

예제 2 UPDATE

반대로 값이 있는 것들만 UPDATE 시키는 것도 가능하다.

UPDATE T_TEST T
SET TEST_NM=
  (SELECT TEST_NM 
  FROM 
    (SELECT
      1 AS TEST_NO
	  , 'TEST00' AS TEST_NM
    FROM DUAL) T2 
  WHERE T.TEST_NO = T2.TEST_NO)
WHERE EXISTS (
  SELECT TEST_NO
  FROM
    (SELECT
       1 AS TEST_NO
     FROM DUAL)T2
   WHERE T.TEST_NO = T2.TEST_NO);

 

이런 식으로 사용하면 된다.