sql

조건값이 NULL일 때 데이터 출력 시 주의 사항(NVL vs CASE문)NVL에 대한 잘못된 이해 바로잡음.

JKimKorea 2021. 12. 1. 14:55

임의로 아래와 같은 테이블 생성

CASE문을 사용해서 LOC_CODE가 NULL 일때와 '3001'일때 SEQ와 LOC_CODE값을 모두 불러오는 SELECT문을

아래와 같이 CASE문을 사용해서 작성해보았더니 NULL일때 값이 조회되지 않았다. 

WITH RT (SEQ, LOC_CODE) AS (
    SELECT 1, '3001' FROM DUAL UNION ALL
    SELECT 2, '3002' FROM DUAL UNION ALL
    SELECT 3, NULL   FROM DUAL UNION ALL
    SELECT 4, '3001' FROM DUAL
)
SELECT A.*
     , NVL(LOC_CODE, '3001') AS LOC_CODE2
  FROM RT A
 WHERE 1=1
   AND LOC_CODE = (CASE LOC_CODE 
                        WHEN '3001' THEN LOC_CODE 
                        WHEN  NULL  THEN NULL 
                   END)

 

결과값

-- 해답: NULL 비교는 IS NULL 을 사용해야 하기 때문이었다. 

WITH RT (SEQ, LOC_CODE) AS (
    SELECT 1, '3001' FROM DUAL UNION ALL
    SELECT 2, '3002' FROM DUAL UNION ALL
    SELECT 3, NULL   FROM DUAL UNION ALL
    SELECT 4, '3001' FROM DUAL
)
SELECT A.*
     , NVL(LOC_CODE, '3001') AS LOC_CODE2
  FROM RT A
 WHERE 1=1
   AND (LOC_CODE = (CASE LOC_CODE 
                        WHEN '3001' THEN LOC_CODE 
                   END)
        OR 
        LOC_CODE IS NULL)

결과값

이번엔 NVL문으로 아래와 같이 작성했다. 

>> 나는 NVL문에 대해 잘못 이해하고 있었다.

해당 컬럼이 NULL인값만 변환해서 데이터를 추출해 준다고 잘못 알고 있었던것,

사실 NULL이 아닐때는 해당 컬럼값을 반환하고, NULL일때는 옆에 써준 대체값을 반환해 주는 함수 이다. 

WITH RT (SEQ, LOC_CODE) AS (
    SELECT 1, '3001' FROM DUAL UNION ALL
    SELECT 2, '3002' FROM DUAL UNION ALL
    SELECT 3, NULL   FROM DUAL UNION ALL
    SELECT 4, '3001' FROM DUAL
)
SELECT A.*
  
  FROM RT A
 WHERE 1=1
   AND NVL(LOC_CODE,'3001') = '3001'

결과값

신세계였다.... 어떻게 이런생각을... ㅋㅋㅋㅋㅋㅋ

머리가 나쁘니 배우는 수 밖에 없다고 생각했다.