data/oracle

[데이터베이스실습] 02_테이블 기초와 SELECT

렁치 2026. 7. 5. 12:00

오늘부터 실제로 데이터를 꺼내봤다. SQL에서 데이터 조회를 담당하는 명령은 SELECT 하나인데, 이 한 명령어에 붙는 절(clause)들의 조합으로 거의 모든 조회가 이뤄진다.

이번엔 실습 환경(SCOTT 계정)을 살펴보고, SELECT의 기본형부터 중복 제거·연산·별칭·정렬까지 손으로 따라가 봤다. 앞으로의 모든 실습이 이 SELECT 위에 쌓이니, 여기서 감을 확실히 잡아두는 게 좋겠다 싶었다.


1. 실습용 계정과 테이블

실습 환경
  • DBMS → Oracle 11g Enterprise Edition
  • 실습 계정 → ID: SCOTT / PW: tiger
  • DBeaver나 SQL*Plus로 접속해 DESC 테이블명; 으로 테이블 구조를 확인할 수 있다.

 

SCOTT 계정에는 오라클 학습에서 수십 년간 표준으로 쓰여 온 세 개의 연습용 테이블이 들어 있다. 이 셋의 구조를 머리에 넣어두니 이후 예제가 훨씬 잘 읽혔다.

 

EMP (사원 정보, 14명)

필드명 설명 유형
EMPNO 사원번호 숫자 4자리
ENAME 사원이름 가변문자열(10)
JOB 직책 가변문자열(9)
MGR 직속 상관의 사원번호 숫자 4자리
HIREDATE 입사일 날짜
SAL 급여 숫자 7자리(소수점 2자리)
COMM 추가수당 숫자 7자리(소수점 2자리)
DEPTNO 소속 부서번호 숫자 2자리

 

DEPT (부서 정보, 4개)

필드명 설명 유형
DEPTNO 부서번호 숫자 2자리
DNAME 부서이름 가변문자열(14)
LOC 부서 위치(지역) 가변문자열(13)

 

SALGRADE (급여 등급, 5개)

필드명 설명 유형
GRADE 급여 등급 숫자
LOSAL 해당 등급의 최소 급여 숫자
HISAL 해당 등급의 최대 급여 숫자

 

EMP의 DEPTNO가 DEPT의 DEPTNO를 참조하고, MGR이 같은 EMP 테이블의 EMPNO를 참조한다는 점을 눈여겨봤다. 또 EMP의 SAL이 SALGRADE의 LOSAL~HISAL 구간에 들어가는 식으로 등급이 매겨진다. 외래키와 범위로 엮인 이 구조가 나중에 조인 실습의 무대가 된다.


2. SELECT 문 기본

SELECT는 관계대수의 프로젝션(원하는 열 고르기)셀렉션(조건에 맞는 행 고르기)을 실제 문법으로 구현한 것이다.

SELECT [조회할 열] FROM [테이블];

 

SELECT * FROM EMP;                    -- 모든 열 (*는 전체 열)
SELECT EMPNO, ENAME, DEPTNO FROM EMP; -- 지정한 열만 (콤마로 나열)
SELECT DEPTNO FROM EMP;               -- 중복값도 그대로 출력됨

 

중복 제거: DISTINCT

SQL의 조회 결과는 기본적으로 중복을 그대로 보여준다. 사원이 14명이고 직책(JOB)에 'CLERK'이 여럿이면 'CLERK'이 여러 번 나온다. "어떤 종류가 있는지"만 보고 싶으면 DISTINCT를 쓴다.

SELECT DISTINCT DEPTNO FROM EMP;        -- 부서번호 종류만
SELECT DISTINCT JOB, DEPTNO FROM EMP;   -- (JOB, DEPTNO) 조합이 같을 때만 중복 제거

 

여러 열에 DISTINCT를 쓰면 열 하나하나가 아니라 그 조합 전체가 같을 때만 중복으로 본다는 점을 기억해뒀다. ALL을 쓰면 중복을 제거하지 않는데, 이게 기본값이라 보통 생략한다.


3. 연산식과 별칭(Alias)

SELECT 절에서는 열을 그대로 꺼낼 뿐 아니라 계산도 할 수 있다.

SELECT ENAME, SAL, SAL * 12 + COMM, COMM FROM EMP;

 

그런데 이렇게 하니 결과의 열 제목이 SAL*12+COMM처럼 그대로 나와 알아보기 어려웠다. 이때 AS별칭(alias)을 붙인다.

SELECT ENAME, SAL, SAL*12 + COMM AS ANNSAL, COMM FROM EMP;
SELECT ENAME AS "사원 이름", SAL+COMM AS "실수령액" FROM EMP;  -- 공백·한글은 큰따옴표

 

NULL이 끼면 계산 결과도 NULL
COMM(수당)이 없는 사원은 그 칸이 NULL이다. 그런데 SAL*12 + COMM처럼 NULL과 산술 연산을 하면 결과가 통째로 NULL이 된다. NULL은 "0"이 아니라 "값을 모름"이라, 모르는 값과의 덧셈 결과도 알 수 없기 때문이다. 엑셀이 빈칸을 0으로 쳐주는 것과 다르다. 그래서 수당까지 포함한 실수령액을 제대로 계산하려면 NULL을 0으로 바꿔주는 NVL 함수가 필요하다(오라클 함수 편에서 다룬다).

 

처음엔 COMM이 비어 있는 사원의 연봉이 통째로 NULL로 나와서 당황했는데, 위 이유를 알고 나니 납득이 됐다. 엑셀 감각으로 빈칸을 0이라 생각한 게 문제였다.


4. 정렬: ORDER BY

조회 결과를 특정 열 기준으로 정렬할 때 ORDER BY를 맨 끝에 붙인다.

SELECT * FROM EMP ORDER BY SAL;               -- 급여 오름차순 (ASC가 기본)
SELECT * FROM EMP ORDER BY SAL DESC;          -- 급여 내림차순
SELECT * FROM EMP ORDER BY DEPTNO, SAL DESC;  -- 부서 오름차순, 그 안에서 급여 내림차순

 

마지막 예처럼 정렬 기준을 여러 개 주면, 앞 기준으로 먼저 묶고 그 안에서 다음 기준으로 정렬한다. 부서별로 묶은 뒤 각 부서 안에서 고액 연봉자부터 보여주는 식이다.


실습 쿼리로 익히기

배운 것을 한데 모아, 직접 던져본 쿼리들이다.

-- 모든 사원의 이름과 연봉(SAL*12)을 연봉 높은 순으로
SELECT ENAME AS "사원이름", (SAL * 12) AS "연봉"
FROM   EMP
ORDER BY "연봉" DESC;          -- 별칭으로 정렬 가능

-- 연봉이 30000 이상인 사원만
SELECT ENAME AS "사원이름", (SAL * 12) AS "연봉"
FROM   EMP
WHERE  (SAL * 12) >= 30000     -- WHERE에는 별칭 못 씀, 연산식을 그대로
ORDER BY "연봉" DESC;

 

ORDER BY는 별칭이 되는데 WHERE는 왜 안 될까?
위 두 번째 쿼리에서 ORDER BY에는 별칭 "연봉"을 썼지만 WHERE에는 (SAL*12)를 그대로 적었다. 이유는 SQL의 처리 순서에 있다. DBMS는 FROM → WHERE → SELECT → ORDER BY 순으로 처리하는데, 별칭은 SELECT 단계에서 비로소 만들어진다. 그래서 SELECT보다 먼저 처리되는 WHERE는 별칭을 알지 못하고, 나중에 처리되는 ORDER BY는 별칭을 쓸 수 있다.

이 차이 때문에 WHERE에 별칭을 썼다가 에러를 한 번 만났는데, 처리 순서를 알고 나니 왜 그런지가 분명해져서 다시는 헷갈리지 않게 됐다.


수업에서 직접 친 쿼리

수업에서는 EMP 테이블로 별칭·중복 제거·정렬·연산식을 차례로 던져봤다.

-- 부서번호를 중복 없이, 내림차순으로
SELECT DISTINCT DEPTNO FROM EMP ORDER BY DEPTNO DESC;

-- (JOB, DEPTNO) 조합 기준 중복 제거
SELECT DISTINCT JOB, DEPTNO FROM EMP;

-- 실수령액(SAL+COMM) — COMM이 NULL인 사원은 결과도 NULL로 나왔다
SELECT ENAME, SAL, COMM, (SAL+COMM) AS RSAL FROM EMP;

 

연봉(SAL*12) 문제를 풀 때, 별칭과 연산식 둘 다로 정렬·조건을 걸어보며 차이를 확인했다.

-- 연봉이 정확히 3600만원인 사원
SELECT ENAME AS "사원이름", (SAL * 12) AS "연봉"
FROM EMP
WHERE (SAL * 12) = 36000;

-- 연봉 3000만원 이상을 내림차순으로 (ORDER BY엔 별칭, WHERE엔 연산식)
SELECT ENAME AS "사원이름", (SAL * 12) AS "연봉"
FROM EMP
WHERE (SAL * 12) >= 30000
ORDER BY "연봉" DESC;

 

ORDER BY에는 별칭 "연봉"이 먹히는데 WHERE에는 (SAL*12)를 그대로 써야 한다는 걸, 같은 문제를 두 방식으로 쳐보며 손으로 확인했다.


오늘 느낀 점

  • SELECT가 관계대수의 프로젝션·셀렉션을 그대로 구현한 거라는 걸 손으로 쳐보니, 이론으로만 보던 σ·π가 실제 문법과 연결됐다.
  • NULL이 계산에 끼면 결과가 통째로 NULL이 되는 건 직접 당해보고서야 몸에 익었다. NULL은 0이 아니라 "모름"이라는 정의를 실습으로 확인한 셈이다.
  • WHERE에 별칭이 안 되는 이유가 SQL 처리 순서라는 점에서, 문법을 외우기보다 처리 순서를 이해하는 게 응용에 강하다는 걸 느꼈다.

한 걸음 더

  • SCOTT/tiger 계정의 SCOTT은 오라클 초기 개발자 Bruce Scott의 이름이고, tiger는 그가 키우던 고양이 이름이라는 일화가 유명하다. 보안상 실무 운영 DB에서는 절대 쓰지 않지만, 학습용 예제 데이터로는 사실상 세계 공용어처럼 자리 잡았다. 요즘 오라클은 더 풍부한 HR 샘플 스키마도 함께 제공한다.
  • SELECT로 만든 열은 원본 테이블을 바꾸지 않는다. SAL*12로 연봉을 계산해 봐도 EMP 테이블의 SAL 값 자체는 그대로다. 조회는 원본을 읽어 새 결과를 만들어내는 연산이라, 데이터를 실제로 바꾸려면 UPDATE가 따로 필요하다. 조회와 변경을 분리해 생각하는 습관이 사고를 예방한다.
  • 정렬은 의외로 비싼 연산이다. 데이터가 많으면 ORDER BY가 전체를 줄 세우느라 시간과 메모리를 크게 쓴다. 그래서 실무에서는 정렬 기준 열에 인덱스를 두거나, 정말 필요한 행만 추린 뒤 정렬하도록 쿼리를 짠다. 지금은 14행짜리 작은 데이터라 체감되지 않지만, "정렬엔 비용이 든다"는 감각은 일찍 가져두는 게 좋다.