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'
신세계였다.... 어떻게 이런생각을... ㅋㅋㅋㅋㅋㅋ
머리가 나쁘니 배우는 수 밖에 없다고 생각했다.