티스토리는 제목 널로했더니 안올라가서 제목이 좀 다릅니다. 양해바람.
0과는 다르다, 0과는!
SQL의 답은 세 개다. 응, 아니, 몰라. 그리고 몰라를 맡고 있는게 NULL이다. 예? 0이 아니예요? 널하고 0은 다른거다. 0은 칸에 0이라는 값이 들어있는거고 NULL은 값이 없는거다. 그러니까 설문조사로 치자면 무응답이 널이고, 0이라고 대답한 게 0이다. 그럼 왜 널은 몰라예요? 설문조사에서 무응답이라고 했잖아요. 뭔 생각을 갖고 있는건지 얘기를 안 하는데 내가 어떻게 앎?
NULL과 연산자(들)
사칙연산
select 1+NULL, NULL+NULL from DUAL; --더하기
select 1-NULL, NULL-NULL from DUAL; --빼기
select 1*NULL, NULL*NULL from DUAL; --곱하기
select 1/NULL, NULL/NULL from DUAL; --나누기
이거 결과로 뭐 나오냐고? 널이요. 위에서 응 아니 몰라의 몰라가 널이라고 했는데, 널은 말 그대로 이게 뭔지 몰라서 연산을 못 한다. 생각해봅시다. 시험을 쳤는데 0점인거는 부정행위를 저질렀거나 아예 공부를 안했는데 찍신 강림도 못해서 0점이지만 널은 시험을 걍 안 친거라 아예 성적을 모르는 상태다. 마치 슈뢰딩거의 고양이인데 박스 까기 5초 전(관측하기 5초 전)이라 뭐든 될 수 있다 이거다. 그러면 모르는 애 데리고 연산하라고 하면 어떻게 돼요?

이렇게 된다. 그러니까 널이랑 사칙연산을 하면 모르는데 어떻게 계산해요! 아 몰라! 해서 다 널된다. 그럼 이걸 처리하는 방법이 있나요? 아, 그것도 이따가 알려드림.
비트윈, IN
select * from HR.JOBS where MIN_SALARY BETWEEN 1000 AND NULL;
비트윈에 널을 쓰면 에러는 안 나는데, 결과를 안 준다. 정확히 말하면 못 주는거다. 이게 뭔 상황이냐면 시험범위 물어봤더니 앞쪽부터 뒤쪽까지라고 하는 상황임. ㅇㅋ? ㅇㅇㅋ
select * from HR.COUNTRIES where COUNTRY_ID IN ('AR','AU');
select * from HR.COUNTRIES where COUNTRY_ID IN ('AR','AU', NULL);
IN 연산자는 얘네들 중 하나라도 일치하면 오케이 콜 하는건데 저기에 NULL이 끼면 뭐 달라지나요? 아뇨, 둘이 결과 똑같습니다. IN에 널이 들어가면 그 널은 걍 없는 애라고 생각하시면 되는데, 문제는 NOT IN이다. NOT IN은 얘네들 빼고 다 달라는 의미인데… 그럼 뭐가 문젠데요?
select * from HR.COUNTRIES where COUNTRY_ID NOT IN ('AR','AU'); --AR, AU빼고 나옴
select * from HR.COUNTRIES where COUNTRY_ID NOT IN ('AR','AU', NULL); --???: 모르는데 어떻게 빼요!
내가 NOT IN은 이거 다 빼고 달라는 얘기라고 했잖아요? 근데 저기에 몰라(=널)가 껴버리면 뭘 빼라는건지 SQL은 판단을 못해서 그냥 결과를 안 준다. 그니까 리터럴리 아무것도 안 준다. 기출문제에 많이 나오는 함정 중 하나인데(다른 하나는 롤업 괄호갖고 장난치는거) NOT IN에 널 들어가면 걍 암것도 안나온다 생각하십쇼.
논리연산자
select TRUE AND NULL, FALSE AND NULL, NULL AND NULL from DUAL; --NULL, FALSE, NULL
select TRUE OR NULL, FALSE OR NULL, NULL OR NULL; --TRUE, NULL, NULL
select NOT NULL from DUAL; --NULL
AND랑 OR은 각각 한쪽이 FALSE, 한쪽이 TRUE일 때 결과가 다른데 이게 왜 그러냐… 를 알려면 쟤가 뭐 하는 앤지를 알아야 한다. AND는 얘랑 얘랑 둘 다 조건이 참이어야 참이고, OR은 둘 중 하나만 참이어도 참이다. 그러니까 FALSE AND NULL은 저놈이 뭔지는 몰라도 같이 끼여든 한쪽이 NULL이니까 FALSE고 TRUE OR NULL은 같이 온 저놈이 뭔지는 몰라도 한쪽이 참이니까 참이다.
비교연산자
select NULL > 1, NULL < 1, NULL = NULL from DUAL;
그거 아십니까? 사실 허수는 크기를 비교할 수 없다고 한다. 왜죠? 허수는 허상이잖아. i가 -1의 제곱이라는 건 알지만 실수가 아니라 이매지너리 넘버니까 상상속의 수잖아요. 그런것처럼 널은 뭐랑 비교하든 비교연산자에서도 널을 토한다. 왜요? 아 모르는 애잖아요. 모르는데 어떻게 비교하냐고. 널이 연산자랑 만나서 뭐가 나오는건 이즈 널(IS NULL)이랑 이즈 낫 널(IS NOT NULL)밖에 없다.
NVL과 NULLIF
둘다 NULL과 관련 있는 연산자인데, NVL(column, B)는 컬럼이 널이면 B로 채우라는 의미이고 NULLIF(A, B)는 A랑 B가 같으면 NULL을, 아니면 A를 내놓아라 이런 얘기. NVL의 경우 NULL을 처리할 때 필요한데, 위에도 썼지만 널은 모르는 애라 뭘 연산하더라도 다 널로 바꾸는 골칫덩이이기 때문이다.
select NULLIF(1, 1), NULLIF(1, 3) from DUAL; --NULL, 1
널이프는 이런 식으로 쓴다.
COALESCE
얘 읽는법 아시는 분 제보 바랍니다. 증말 읽기 개같이 어렵다. 아무튼 코알레스 이놈은 뭐냐… COALESCE(A, B, C) 형식으로 쓰고 최초로 널이 아닌 값을 반환하는 함수다. 그러니까 어떻게든 널을 땜빵하려는 의지가 보이는(…) 함수인데… 어떻게 채우냐고? A가 널이 아니면 A, A가 널이면 B, B도 널이면 C, C까지 널이면 그제서야 널을 반환한다.
select COALESCE(NULL, '미끄메라', NULL, '미끄네일', NULL, '미끄래곤') from DUAL; --미끄메라
처음으로 나타나는 널이 아닌 값이 미끄메라이기 때문에 여기서는 미끄메라를 반환한다.
공집합도 있다!
심지어 당신이 생각하는 그 공집합이 맞다. 근데 널이랑 공집합은 또 다른 개념이다. 널은 값이 없는거고 공집합은 없는 거 내놓으라고 하면 주는건데, 일단 터미널에서는 둘다 빈 칸이다. 그러니까 널은 남자친구는 있는데 정보가 없는거고 공집합은 남자친구 질량이 0인거다. 그냥 없다. 아니 없다고요. 울지말고. 괜찮아 오랫동안 없었어.