본문 바로가기
DataBase/Oracle

DQL) SELECT 구문 (가상 컬럼, nvl()함수, 별칭 alias, 중복 값 제거 distinct, 문자열 연결 연산자 ||, '+' 연산 기호)

by 박채니 2022. 4. 14.

안녕하세요, 코린이의 코딩 학습기 채니 입니다.

 

개인 포스팅용으로 내용에 오류 및 잘못된 정보가 있을 수 있습니다.


SELECT 구문

- 실제 결과 집합 (result set)의 컬럼을 제한

- 존재하지 않는 컬럼도 조회 가능

- 가상 컬럼 (연산 처리 결과 등) 사용 가능

- 123, '안녕' 같은 리터럴도 행 수만큼 반복 출력 가능


☞ 가상컬럼

select
    emp_name,
    salary,
    salary * 12, -- 가상 컬럼
    '안녕'
from 
    employee;

emp_name, salary는 기존에 존재하던 데이터였지만 salary*12와 '안녕'은 실제 존재하던 데이터가 아니였습니다.

하지만 잘 조회되는 것을 확인할 수 있죠?

게다가 salary*12는 기존 salary 데이터에 12를 곱한 값이 잘 출력이 된 것을 확인할 수 있습니다.

'안녕' 또한 행 수만큼 반복 출력 되는 것을 볼 수 있습니다.

 

만약 실급여 계산을 salary + (salary * bonus) 로 하고 싶다면 어떻게 할까요?

마찬가지로 가상 컬럼을 만들어주면 됩니다.

select
    emp_name,
    salary,
    salary * 12, -- 가상 컬럼
    salary + (salary * bonus)    
--    '안녕'
from 
    employee;

하지만 결과 값은 기대했던 바와는 다르게 조금 이상한 것을 확인할 수 있는데요,

(null)이라는 값들이 반환된 행들이 몇 있습니다.

 

 

☞ null 값의 비밀

그 이유는, 보너스 컬럼의 데이터들 중 (null) 값이 있었기 때문입니다.

null과는 어떠한 연산 (산술연산, 비교연산)이 불가합니다.

따라서 null과의 연산 결과는 반드시 null 이기 때문에 위처럼 이상한 결과값이 나오게 되는 것이죠.

 

예로 null에 산술연산을 해보았습니다.

select    
    null + 1, null - 2, null * 3, null / 4
from
    dual;

+, -, *, / 모든 산술연산의 결과가 (null)인 것을 확인할 수 있습니다.

 

다시 돌아가서, 그렇다면 salary + (salary * bonus) 은 계산할 수 없는 식일까요?

이 때, nvl 함수를 이용하면 됩니다.

 

 

☞ nvl(nullalbeValue, nullValue)

- null 처리 함수

select
    nvl('abc', 'xxx'),
    nvl(null, 'xxx')
from
    dual;

nvl 함수는 값이 null 인 경우에는 지정값을 출력하고, null이 아닌 경우에는 원래 값을 그대로 출력하는 함수입니다.

따라서 'abc', 'xxx' 는 'abc'가 null이 아니므로 'abc'가 출력된 것을 확인할 수 있고,

null, 'xxx'는 null이 null 이므로, 지정 값인 'xxx'가 출력 된 것을 확인할 수 있습니다.

 

select
    emp_name,
    salary,
--    salary * 12, -- 가상 컬럼
--    salary + (salary * bonus),
    bonus,
    nvl(bonus, 0),
    salary + (salary * nvl(bonus, 0))
--    '안녕'
from 
    employee;

bonus 값이 null이라면 0으로 출력하여 실급여 계산을 하였습니다.

 

여기서, 컬럼명이 보기 좋지 않아서 수정을 하고 싶은데요.

 

☞ 별칭 alias

- result set의 컬럼명으로 사용

- as "별칭"의 형식이지만, as와 ""는 생략 가능

- 숫자로 시작하는 별칭, 공백/특수문자가 포함된 별칭은 "" 생략 불가

select
    emp_name as "사원명",
    emp_no "주민번호",
    phone 전화번호,
    dept_code "직급 코드",       -- 공백이 있으므로 반드시 ""로 감싸주기
    job_code "1_직급"             -- 숫자로 시작/특수문자가 포함되었으므로 반드시 ""로 감싸주기
from
    employee;

컬럼명이 훨씬 깔끔해져서 보기 좋습니다..!

 

☞ 중복 값 제거 distinct

- select 구문 맨 앞에 한 번만 사용 가능

- 여러 컬럼에 사용 시, 여러 컬럼을 합쳐서 중복 여부 판단

select distinct
    dept_code
from
    employee;

 

여러 컬럼 사용 시, 합쳐서 중복 여부를 판단한다고 하였습니다.

dept_code와 job_code에 사용하게 된다면 위에서 차례대로 (D9, J1)을 하나로 보고 합쳐서 중복 여부를 판단하게 되는 것입니다.

 

select distinct
    dept_code, job_code
from
    employee;

 

☞ 문자열 연결 연산자 ||

- 숫자만 (+ 연산) 가능

select
    '오, ' || emp_name || '님, 안녕하세요^^' "인사말"
from
    employee;

 

select
--    '오, ' || emp_name || '님, 안녕하세요^^' "인사말"
    '오' + emp_name + '님, 안녕하세요^^' "인사말"
from
    employee;

"ORA-01722: invalid number"
다른 언어와 헷갈려서 문자열 연결 시 '+'를 쓴다면 위와 같은 에러 코드가 뜨게 됩니다! (유의하기)

 

 

☞ '+' 연산 기호의 비밀

- +의 좌항/우항을 반드시 숫자로 처리

- 문자인 경우도 자동으로 숫자형으로 변환 → 숫자가 아니라면 오류 발생

select
    1 + 123,
    1 + '123'
from
    dual;

1 + '123'에서 '123'은 문자형의 '123'을 의미하였지만, '+'는 자동으로 숫자형으로 변환되기 때문에 '123'을 숫자형을 변환 후 연산 수행한 것을 확인할 수 있습니다.


@실습 문제1

1. 사원 테이블에서 이름, 월 실수령액, 실 연봉 조회
월 실수령액 : 월 급여 - (월 급여 * 3.3%)
월 급여 : salary + (salary * bonus)

-- @실습문제
-- 1. 사원 테이블에서 이름, 월 실수령액, 실 연봉 조회
-- 월 실수령액 : 월 급여 - (월 급여 * 3.3%)
-- 월 급여 : salary + (salary * bonus)
select
    emp_name "이름",
    salary + (salary * nvl(bonus, 0)) - ((salary + (salary * nvl(bonus, 0))) * 0.033) "월 실수령액",
    (salary + (salary * nvl(bonus, 0)) - ((salary + (salary * nvl(bonus, 0))) * 0.033)) * 12 "실 연봉"
from
    employee;

 

2. 사원 테이블에서 이름, 입사일, 근무일수 조회

-- 2. 사원 테이블에서 이름, 입사일, 근무일수 조회
-- 소수점처리 floor()
select
    emp_name "이름",
    hire_date "입사일",
    floor(sysdate - hire_date) "근무일수"   -- floor() 버림처리
from
    employee;