본문 바로가기

별걸다하는 IT/데이터베이스 Database

[sql, 오라클]NULL 개념, NULL 중요도와 연산, 선택, NULL관련 함수 종류, NULL 정렬[NULLS FIRST, NULLS LAST]

 

 

 

 

 

 

 

 

데이터베이스(DB, DBMS) 목차

 

NULL의 의미

아직 정의되지 않은 값

0과 공백이랑은 다릅니다!! 0은 개수가 0개!와 같이 없다는 값 즉 숫자이고 공백은 하나의 문자이지만

NULL은 unknown 또는 N/A(not applicable)이라는 의미로 쓰여요. 즉 알 수 없거나 존재하지 않기에 적용할 수 없다는 거~ 값자체가 존재하지 않다! 없다! 는 거입니다. 

 

***근데 오라클의 경우에는 사용자가 ' '를 VARCHAR2 데이터 타입에 INSERT를 하면

내부에서 자동적으로 NULL로 바꿔서 저장해줌 ( 오라클은 공백 문자열이 저장되는 걸을 허용하지 않음 그냥 NULL로 처리)

 

그래서 테이블을 생성할 때 기본키는 NULL일 수가 없다는 조건이 붙습니다. (not null이어야만 한다) 기본키는 사람을 식별해주는 주민등록번호처럼 데이터를 식별해줄 수 있는 키이기 때문이죠.

예를 들어 주민등록번호 없는 사람이 없듯이, 사람이라면 주민번호를 가지고 있어야 함을 강제하는 것 (null이면 안돼)

기본키는 not null이기 때문에 데이터를 구별할 수 있고, 마찬가지로 주민등록번호도 사람 테이블의 기본키가 될 수 있다는 것!

 

데이터를 정렬할때 NULL은 어느 위치를 갖는가? NULLS FIRST, NULLS LAST

오라클과 MySQL에서는 NULL을 가장 큰 값으로 간주!

SQL SERVER NULL 가장 작은 값으로 간주!

이 기준으로 정렬됩니다.

 

근데 이게 맘에 안들어서 null을 가장 마지막에 오게 하도록 하고 싶다!

내림차순이면 큰수-> 작은 수 이렇게 정렬되어야 하는데 오라클에서 null이 앞에 오는게 싫다.

 

NULL을 맨 앞이나 맨 뒤로 정렬하는 법

[ORACLE]

null 마지막으로 가게 해줘 키워드 - NULLS LAST

반대 개념으로는 NULLS FIRST 사용하면 됩니다.

order by goods_code desc nulls last
order by goods_code desc nulls first

order by [필드명] desc nulls last

order by [필드명] desc nulls first

 

[MYSQL]

그런데 MySQL에서는 NULLS FIRST, NULLS LAST라는 명령어가 없어요

null을 가장 먼저 앞에 정렬하고 싶을 때

그럴 경우 desc를 두 번 사용해서 구현해주면 돼요. NULL을 먼저 정렬하고, 그 다음 값들을 정렬합니다.

 

 

 

 

NULL 연산

null 값을 표함하는 연산의 결과 값 또한 NULL!

NULL +2 = NULL

NULL - 2 = NULL

NULL * 2 = NULL

NULL / 2 = NULL, 2/NULL = NULL

모르는 데이터에 숫자를 더하거나 빼도 결과는 마찬가지로 모르는 데이터이기 때문~~

[NULL의 연산 결과를 보여주는 표]

sum(), avg() 등의 함수에 NULL값이 있으면 NULL을 무시하고 수행!

마치 존재하지 않는 행처럼..ㅎ

 

NULL 선택 (IS NULL, IS NOT NULL)

NULL은 값이 아니기 때문에 '!=', '^=', '<>' ,'=' 등의 표현은 먹지 않습니다.

 

컬럼이 NULL 인 경우만 추출해서 보고 싶을 경우

IS NULL / IS NOT NULL(null이 아닌 경우) 키워드를 사용함

select *
from customers
where phone is not null

예시

 

NULL 관련 함수 엿보기

결과 값이 NULL이 아닌 다른 값을 얻고자 할 때 NVL/ISNULL 함수를 많이 쓴다

null 값의 대상이 숫자 유형 데이터인 경우는 주로 0으로, 문자 유형 데이터인 경우는 'x' 같이 해당 시스템에서 의미 없는 문자로 바꾸는 경우가 많음

 

 NVL (expr1, expr2) (oracle)

 ISNULL(expr1, expr2) (sql server)

 expr1 값이 널인 경우 expr2 값을 반환하며

 그렇지 않은 경우 expr1 값을 반환한다.

 expr1, expr2 데이터타입이 달라도 된다.

 자동으로 오라클에서 변환해서 적용해줌

 NVL2(expr1, expr2, expr3)

 expr1이 널이 아닌 경우, expr2를 반환한다.

 expr1이 널인 경우 expr3을 반환한다.

 

 NULLIF(expr1, expr2)

 두 표현식을 비교하여 동일할 경우 널을 반환하고 동일하지 않은 경우 첫번째 식을 반환한다.

 수 타입이 아닐 경우 에러남

 COALESCE(expr1, expr2, ..., exprn)

 표현식 목록에서 NULL이 아닌 첫 번째 표현식을 반환한다.

 expr1이 NULL이 아니면 expr1 값을 그렇지 않으면 COALESCE(expr2, expr3, ...)값을 반환.

 

 

문제로 연습하기~

(1) 다음 중 아래 TAB1을 보고 각 SQL 실행 결과를 가장 올바르게 설명한 것을 고르시오.

[TAB1]

 COL2

 COL2 

 a 

 NULL 

 b 

 '' 

 c  

 3 

 d 

 4  

 e  

 3 

 

1. SELECT COL2 FROM TAB1 WHERE COL1 = 'b';

-> 실행 결과가 없다.(공집합)

2. SELECT ISNULL(COL2, 'x') FROM TAB1 where COL1='a';

-> 실행 결과로 'x'를 반환한다.

3. SELECT COUNT(COL1) FROM TAB1 WHRER COL2 = NULL;

실행 결과는 1이다.

4. SELECT COUNT(COL2) FROM TAB1 WHERE COL1 IN ('b', 'c');

->실행 결과는 1이다.

 

(2) 사원 테이블에서 MGR의 값이 7698과 같으면 NULL을 표시하고, 같지 않으면 MGR을 표시하려고 한다.

아래 SQL 문장의 [ㄱ] 안에 들어갈 함수명을 작성하시오

 

SELECT ENAME, EMPNO, MGR, [ㄱ](MGR, 7698) as NM FROM EMP;

 

 

(3) 다음 중 아래와 같은 데이터 상황에서 SQL의 수행 결과로 가장 적절한 것은?

TAB1

 C1

 C2 

 C3 

 1 

 2 

 3 

 

 2 

 3 

 

 

 3 

SELECT SUM(COALESCE (C1, C2, C3)) FROM TAB1

1. 0 2. 1 3. 6 4. 14

 

(4) 아래의 각 함수에 대한 설명 중 [ㄱ], [ㄴ], [ㄷ]에 들어갈 함수를 차례대로 작성하시오

[ㄱ] (표현식1, 표현식2) : 표현식1의 결과값이 NULL이면 표현식 2의 값을 출력한다

[ㄴ] (표현식1, 표현식2) : 표현식1과 표현식2와 같으면 NULL을, 같지 않으면 표현식 1을 리턴한다

[ㄷ] (표현식1, 표현식2) : 임의의 개수 표현식에서 NULL이 아닌 최초의 표현식을 나타낸다.

 

(5) 다음 중 아래 각각 3개의 SQL 수행 결과로 가장 적절한 것은?

SELECT AVG(COL3) FROM TAB_A;

SELECT AVG(COL3) FROM TAB_A WHERE COL1>0;

SELECT AVG(COL3) FROM TAB_A WHERE COL1 IS NOT NULL;

 COL1

 COL2 

 COL3 

 30 

 NULL 

 20 

 NULL 

 40 

 0 

 0  

 10  

 NULL 

 

1. 20, 20, 20 2. 20, 10, 10 3. 10,20,20 4. 10,10,10

 

(6) 다음 SQL 문장 중 COLUMN1의 값이 널(NULL)이 아닌 경우를 찾아내는 문장으로 가장 적절한 것은? (ANSI 표준 기준)

1. SELECT * FROM MYTABLE WHEE COLUMN1 IS NOT NULL

2. SELECT * FROM MYTABLE WHEE COLUMN1 IS <> NULL

3. SELECT * FROM MYTABLE WHEE COLUMN1 != NULL

4. SELECT * FROM MYTABLE WHEE COLUMN1 NOT NULL

 

 

(7) 아래와 같은 DDL 문장으로 테이블을 생성하고 SQL들을 수행하였을 때 다음 설명 중 옳은 것은?

CREATE TABLE 서비스

(

서비스번호 VARCHAR2(10) PRIMARY KEY,

서비스명 VARCHAR2(100) NULL,

개시일자 DATE NOT NULL

);

[SQL]

ㄱ. SELECT * FROM 서비스 WHERE 서비스번호 =1;

ㄴ. INSERT INTO 서비스 VALUES('999', '', '2015-11-11');

ㄷ. SELECT * FROM 서비스 WHERE 서비스명 ='';

ㄹ. SELECT * FROM 서비스 WHERE 서비스명 IS NULL;

 

1. 서비스번호 컬럼에 모든 레코드 중에서 '001'과 같은 숫자 형식으로 하나의 레코드만이라도 입력되어 ㄱ은 오류없이 실행된다.

2. ORACLE에서 ㄴ과 같이 데이터를 입력하였을 때, 서비스명 컬럼에 공백문자 데이터가 입력된다.

3. ORACLE에서 ㄴ과 같이 데이터를 입력하고, ㄷ과 같이 조회하였을 때 데이터는 조회된다.

4. SQL SERVER에서 ㄴ과 같이 데이터를 입력하고 ㄹ과 같이 조회하였을 때, 데이터는 조회되지 않는다.

 

 

(8) 어느 기업의 직원 테이블(EMP)이 직급(GRADE)별로 사원 500명, 대리 100명, 과장 30명, 부장5명 직급이 정해지지 않은(NULL)사람 25명으로 구성되어 있을 때, 다음 중 sql문을 sql1)부터 sql3)까지 순차적으로 실행한 결과 건수를 순서대로 나열한 것으로 가장 적절한 것은?

SQL1) SELECT COUNT(GRADE) FROM EMP;

SQL2) SELECT GRADE FROM EMP WHERE GRADE IN ('차장','부장','널');

SQL3) SELECT GRADE, COUNT(*) FROM EMP GROUP BY GRADE;

 

1. 670, 15, 5

2. 645, 40, 5

3. 645, 15, 6

4. 670, 40, 6

문제 출처 : SQLD, SQLP