[강의] DB_DML(SELECT)

Jerry·2025년 8월 25일

DML(SELECT)

SQL(Structured Query Language) 개념

관계형 데이터베이스에서 데이터를 조회하거나 정의 및 조작하기 위해 사용하는 표준 언어
선언형 고급 언어(Declarative High-Level Language)로 고급 언어보다 더 높은 단계의 언어이다.
데이터를 무엇을 할지(What) 선언 하면, 어떻게 처리할지(How)는 DBMS가 알아서 처리한다.

주요 데이터 타입 (PostgreSQL)

분류상위 타입하위 타입 및 크기설명
수치형 (Numeric)정수형 (Integer)SMALLINT (2B)
INTEGER/INT (4B)
BIGINT (8B)
정수 저장, 크기에 따라 범위 다름
INTEGER ↔ INT 별칭 존재
실수형 (Float)REAL (4B)
DOUBLE PRECISION (8B)
부동소수점 또는 고정소수점 저장
임의 정밀도NUMERIC, DECIMAL지정된 정밀도의 소수 저장, 금융 데이터 적합
예: NUMERIC(4,2) → 총 4자리, 소수점 2자리
시퀀스형SMALLSERIAL (2B)
SERIAL (4B)
BIGSERIAL (8B)
내부적으로 시퀀스 기반 자동 증가 정수
AUTO INCREMENT 전용
문자형 (String)고정길이 문자CHAR(n)설정된 길이보다 짧으면 공백으로 채움
검색 속도 및 인덱스 구성에 유리
가변길이 문자VARCHAR, VARCHAR(n)가변 길이 문자, 행 크기로 8KB 제한
최대 크기 지정 가능
TEXTTEXT길이 제한 없음, VARCHAR와 동일 문법
논리형BOOLEANBOOLEAN (1B)참/거짓 표현 (TRUE, FALSE, NULL 가능)
BinaryBYTEABYTEABinary Data 저장 (이미지, 음성 등)
최대 크기: 65,535 / 16,777,215 / 4,294,967,295
Date TimeDATEDATE연, 월, 일 저장
TIMETIME
TIME WITH TIME ZONE (TIMEZ)
시, 분, 초 저장
TIMEZ는 별칭으로, 타임존 정보 포함
TIMESTAMPTIMESTAMP
TIMESTAMP WITH TIME ZONE (TIMESTAMPTZ)
날짜와 시간 저장 (UTC 기준)
WITH TIME ZONE 사용 시 타임존 적용
TIMESTAMPTZ는 별칭
열거/배열ENUMCREATE TYPE gender AS ENUM ('male','female');사전에 정의된 문자열 집합 중 하나만 선택
datatype[]예: interests TEXT[]동일 타입 요소들의 배열 저장 가능
기타JSONJSON, JSONBJSON 객체 구조 저장 가능
JSONB는 바이너리 최적화 및 빠른 검색 지원
UUIDUUID범용 고유 식별자 (Universally Unique Identifier)
범위 (Range)int4range, int8range, numrange,
tsrange, tstzrange, daterange
값의 구간을 표현하는 타입 (숫자, 날짜, 시간 등)
네트워크 주소INET, CIDR, MACADDRIP 주소, 네트워크 대역, MAC 주소 저장
기타 특수XML, tsvector, tsquery,
point, line, circle, box, polygon
XML 데이터, Full-text 검색(tsvector/tsquery), 공간/수학 관련 타입

DB 스키마 전환

DB 스키마 전환은 데이터베이스 내에서 객체가 속하는 논리적 공간을 변경하는 개념이다.
PostgreSQL은 데이터베이스와 스키마를 구분하여 관리한다. 데이터베이스 전환은 연결 변경으로, 스키마 전환은 SET search_path로 수행한다. 이후 DB의 이름을 생략할 수 있다.
Ex) SELECT FROM schema_name.table_name → SELECT FROM table_name

-- 1. 데이터베이스 생성
CREATE DATABASE my_database;
-- 2. 연결된 DB 안에서 스키마 생성
CREATE SCHEMA my_schema;
-- 3. 스키마 삭제
DROP SCHEMA my_schema CASCADE;
-- 4. 특정 스키마를 기본 검색 경로로 설정
SET search_path TO my_schema;
COMMIT;

SELECT 문

SELECT는 관계형 데이터베이스에서 원하는 데이터를 조회(Query)하기 위한 기본적인 SQL 명령어
조회한 결과는 Result Set이라 말하며, SELECT구문에 의해 반환된 행들의 집합을 의미
Result Set은 0개 이상의 행이 포함될 수 있이며, 특정 기준에 의해 정렬 가능
한 테이블의 특정 컬럼, 행, 행/컬럼 또는 여러 테이블의 특정 행/컬럼 조회 가능

SELECT * FROM employee

SELECT 문 작성법

SELECT 컬럼 [, 컬럼, …] ← 컬럼명 소문자 권장
FROM 테이블 ← 테이블명 소문자 권장
WHERE 조건식; ← 조건식 컬럼명은 소문자 키워드는 대문자 권장

SELECT

조회하고자 하는 컬럼명 기술
여러 컬럼을 조회하는 경우 컬럼은 쉼표로 구분하고, 마지막 컬럼 다음은 쉼표를 사용하지 않음
모든 컬럼 조회 시 컬럼 명 대신 * 기호 사용 가능하며 조회 결과는 기술한 컬럼 명 순으로 표시 됨

FROM

조회 대상 컬럼이 포함된 테이블 명을 기술, DB 명이 앞에 붙어도 무관

WHERE

행을 선택하는 조건 기술
여러 개의 제한 조건을 포함할 수 있으며, 각각의 제한 조건은 논리 연산자로 연결
제한 조건을 만족시키는 행들만 Result Set에 포함

SELECT 예시

기본

-- 직원 전부의 사번과 이름, 월급을 조회하는 구문
SELECT emp_id, emp_name, salary
FROM codeit.employee;
-- 또는
SELECT emp_id, emp_name, salary
FROM employee;
-- 직원 전부의 모든 정보를 조회하는 구문 → Full scan이 말한다.
SELECT emp_id, emp_name, emp_no, email, phone, dept_code,
job_code, sal_level, salary, bonus, manager_id, hire_date,
ent_date, ent_yn
FROM employee;
-- 또는
SELECT * FROM employee;*로 컬럼명, SPACE 생략 가능! *은 개발 시 추천하지 않음

컬럼 값 산술 연산

-- 컬럼 값에 대해 산술 연산한 결과 조회 가능
SELECT emp_name, salary * 12, (salary + (salary*bonus)) * 12
FROM employee;

AS문 - 컬럼 별칭(Column Alias)

-- 'AS 별칭', '별칭' 또는 'AS "별칭"'을 기술하여 컬럼 별칭을 지을 수 있음
-- → 매우 유용한 스킬로 DB 연동 시 컬럼명 기준임으로 복잡한 컬럼명 단축이 가능
SELECT emp_name AS 이름, salary * 12 "연봉(원)",
(salary + (salary * bonus)) * 12 AS "총 소득(원)"
FROM employee;
-- * 숫자 혹은 특수문자가 포함되는 경우에 " " 사용
-- * AS 생략 가능(공백으로 구분)

리터럴(literal)

-- 임의로 지정한 문자열을 SELECT절에 사용하면 테이블에 존재하는 데이터처럼 활용
SELECT emp_id, salary, '원' AS 단위
FROM employee;
-- * 문자나 날짜 리터럴은 ‘ ‘ 기호 사용
-- * 리터럴은 Result Set의 모든 행에 반복 표시 됨

DISTINCT(중복 제거)

-- 컬럼에 포함된 데이터 중복된 데이터를 제거하고 유일한 값만 조회할 때 사용,
-- 여러 컬럼 기준으로도 중복제거가 가능하며 count절과 조합하면 중복이 제거된 수를 알 수 있음
SELECT DISTINCT job_code FROM employee;SELECT count(DISTINCT job_code) FROM employee;
SELECT DISTINCT job_code, dept_code FROM employee;

WHERE절

-- 검색할 컬럼의 조건을 설정하여 행 결정, 이때 조건은 다중 논리 조건 활용 가능
-- - 부서코드가 ‘D9’인 직원의 이름, 부서코드 조회
SELECT emp_name, dept_code
FROM employee
WHERE dept_code = 'D9';
-- - 부서코드가 ‘D2’보다 사전순으로 낮은 직원의 이름, 부서코드 조회
SELECT emp_name, dept_code
FROM employee
WHERE dept_code <= 'D2'; -- 문자열도 대소 비교가능!
-- 검색할 컬럼의 조건을 설정하여 행 결정, 이때 조건은 다중 논리 조건 활용 가능
-- - 급여가 4000000보다 많은 직원 이름과 급여 조회
SELECT emp_name, salary
FROM employee
WHERE salary > 4000000;
-- - 입사일이 2020년 이후인 직원
SELECT emp_name, salary, hire_date
FROM employee
WHERE hire_date > '2020-01-01';
-- 여러 개 조건 작성 시 AND/OR 사용 → 연산자 우선순위 존재!!!
-- - 부서코드가 D6이고 급여를 2000000보다 많이 받는 직원의 이름, 부서코드, 급여 조회
SELECT emp_name, dept_code, salary
FROM employee
WHERE dept_code = 'D6' AND salary > 2000000;
-- - 부서코드가 D6이거나 급여를 2000000보다 많이 받는 직원의 이름, 부서코드, 급여 조회
SELECT emp_name, dept_code, salary
FROM employee
WHERE dept_code = 'D6' OR salary > 2000000;

논리 연산자(Logical Operators)

여러 개의 제한 조건 결과를 하나의 논리 결과로 만들어 주는 연산자

연산자설명
AND여러 조건이 동시에 TRUE일 경우에만 TRUE값 반환
OR여러 조건들 중에 어느 하나의 조건만 TRUE이면 TRUE값 반환
NOT조건에 대한 반대 값으로 반환(NULL 제외)

※ 연산자 우선순위는 NOT > AND > OR

AND 연산 결과

TRUEFALSENULL
TRUETRUEFALSENULL
FALSEFALSEFALSEFALSE
NULLNULLFALSENULL

OR 연산 결과

TRUEFALSENULL
TRUETRUETRUETRUE
FALSETRUEFALSENULL
NULLTRUENULLNULL

비교 연산자(Comparison Operators)

표현식 사이의 관계를 비교하기 위해 사용 결과는 논리 결과(TRUE/FALSE/NULL) 중 하나가 된다.
동적 타이핑이 가능해서 비교 연산 시 자동으로 타입을 맞춰 주지만 완벽하진 않다.
비교 연산자 사용 시 숫자, 문자, 날짜 type까지 대소 비교가 가능하다!

연산자의미예시설명
=같음age = 30age가 30인 행
!= 또는 <>같지 않음city != 'Seoul'서울이 아닌 도시
>보다 큼score > 80점수가 80 초과
<보다 작음price < 10000가격이 1만원 미만
>=크거나 같음age >= 18성인 이상
<=작거나 같음discount <= 2020% 이하 할인
IS NULLNULL 여부email IS NULL이메일이 없는 경우
IS NOT NULLNULL 아님phone IS NOT NULL전화번호 있는 경우
BETWEEN A AND B범위 내 포함score BETWEEN 70 AND 9070 이상 90 이하
IN (...)목록 안에 있음grade IN ('A', 'B')A 또는 B 등급
NOT IN (...)목록에 없음id NOT IN (1, 2, 3)ID가 1, 2, 3이 아닌 경우
LIKE패턴 일치name LIKE 'abc%'abc로 시작하는 이름
ILIKE (PostgreSQL 전용)패턴 일치 (대소문자 구분X)name ILIKE 'abc%'ABC 또는 abc로 시작하는 이름
NOT LIKE패턴 불일치email NOT LIKE '%.com'.com으로 끝나지 않는 이메일

BETWEEN AND

비교하려는 값의 범위를 표현 할 수 있는 문법
만일 포함되면 TRUE를 리턴 하는 연산자 상한 값과 하한 값의 경계도 포함됨

  • 급여를 3500000보다 많이 받고 6000000보다 적게 받는 직원 이름과 급여 조회
SELECT emp_name, salary
FROM employee
WHERE salary >= 3500000 AND salary <= 6000000;
-- 또는
SELECT emp_name, salary
FROM employee
WHERE salary BETWEEN 3500000 AND 6000000;

LIKE 절

비교하려는 값이 지정한 특정 패턴을 만족하면 TRUE를 리턴 하는 연산자
'%'와 '_'를 와일드 카드로 사용, 와일드 카드는 문자열 앞과 뒤에 표기 될 수 있음
Ex) '홍%', '%길동', '%길%', '_길동', '홍__', '_길_'

  • '동훈' 이름을 가진 직원 이름과 급여 조회
SELECT emp_name, salary
FROM employee
WHERE emp_name LIKE%동훈’;
  • 핸드폰의 앞 네 자리 중 첫 번호가 7인 직원 이름과 전화번호 조회
SELECT emp_name, phone
FROM employee
WHERE phone LIKE ‘___7%;

LIKE절 ESCAPE 문법

와일드 카드 문자와 패턴의 특수문자가 동일한 경우 어떤 것을 패턴으로 결정하는지 구분하지 못하기 때문에 데이터로 처리할 와일드 카드 문자 패턴 기호 앞에 임의의 특수문자를 사용하고 ESCAPE OPTION으로 등록하여 처리

  • EMAIL ID 중 '_'의 앞이 2자리인 직원 이름, 이메일 조회
SELECT emp_name, email
FROM employee
WHERE email LIKE '__ _#_%' ESCAPE '#';

NOT LIKE

LIKE절의 부정표현으로 'NOT' 키워드를 활용할 수 있음

  • '이'씨 성이 아닌 직원 사번, 이름, 이메일 조회
SELECT emp_id, emp_name, email
FROM employee
WHERE emp_name NOT LIKE ‘이%;
-- 또는
SELECT emp_id, emp_name, email
FROM employee
WHERE NOT emp_name LIKE ‘이%;

IS NULL과 IS NOT NULL

값의 NULL 여부를 확인 하는 유일한 연산자, = NULL은 잘못된 표현이다.
NULL은 데이터 공백을 의미하며, 빈문자열과 0과 다르다.

  • 관리자도 없고 부서 배치도 받지 않은 직원 조회
SELECT emp_name, manager_id, dept_code
FROM employee
WHERE manager_id IS NULL AND dept_code IS NULL;
  • 부서 배치를 받지 않았지만 보너스를 지급받는 직원 조회
SELECT emp_name, bonus, dept_code
FROM employee
WHERE dept_code IS NULL AND bonus IS NOT NULL;

IN / NOT IN 연산자

IN은 비교하려는 값 목록(다수)에 일치하는 값이 있으면 결과를 반환하는 연산자
NOT IN은 포함하지 않는 결과를 반환 할 때 활용하는 연산자
→ 생각보다 매우 중요한 연산자로 상품의 카테고리 체크 할 때 자주 사용

  • D6 부서와 D8 부서원들의 이름, 부서코드, 급여 조회
SELECT emp_name, dept_code, salary
FROM employee
WHERE dept_code IN (‘D6’, ‘D8’);
-- 또는
SELECT emp_name, dept_code, salary
FROM employee
WHERE dept_code = ‘D6’ OR dept_code = ‘D8’;

연산자 우선순위

우선순위연산자
0(괄호)
1산술 연산자 +-*/%
2연결 연산자
3비교 연산자 = >
4IS NULL / IS NOT NULL , LIKE , IN / NOT IN
5BETWEEN AND / NOT BETWEEN AND
6논리 연산자 – NOT
7논리 연산자 – AND
8논리연산자 – OR
  • J2 또는 J7 직급 코드 중 급여를 2000000보다 많이 받는 직원의 이름, 급여, 직급코드 조회
SELECT emp_name, salary, job_code
FROM employee
WHERE job_code = ‘J7’ OR job_code = ‘J2’ AND salary > 2000000; -- 잘못된 쿼리
-- * 연산자 우선 순위에 의해서 AND가 먼저 실행됨
-- J2직급의 급여 2000000 이상 받는 직원이거나 J7직급인 직원이라는 의미
SELECT emp_name, salary, job_code
FROM employee
WHERE (job_code = ‘J7’ OR job_code = ‘J2’) AND salary > 2000000;
-- * 우선순위를 고려하여 OR가 먼저 처리 되도록 ( )를 이용해 우선 순위 변경
-- J7 직급이거나 J2직급인 직원들 중 급여 2000000 이상 받는 직원이라는 의미

ORDER BY, LIMIT, OFFSET 절

SELECT한 컬럼에 대해 정렬을 할 때 작성하는 구문으로 SELECT 구문의 가장 마지막에 작성하며 실행 순서 역시 가장 마지막에 수행됨 (우선순위가 가장 낮음)
LIMIT절은 행의 개수를 제한하는 문장으로 ORDER BY 보다 우선순위가 낮다.
OFFSET은 LIMIT절 수행 시 OFFSET(넘어갈) 개수를 지정하는 문장이다.

SELECT 컬럼 명 \[, 컬럼명,]
FROM 테이블 명
WHERE 조건식
ORDER BY 컬럼명 | 별칭 | 컬럼 순번 정렬방식 [NULLS FIRST | LAST];
LIMIT, OFFSET/*
* 정렬 방식
- ASC : 오름차순(Ascending)
- DESC : 내림차순(Descending)
*/

ORDER BY

  • EMPLOYEE에서 EMP_ID로 ASC(오름차순), DESC(내림차순) 정렬
SELECT * FROM employee ORDER BY emp_id ASC; OR DESC; -- 생략 시 ASC 정렬
  • EMPLOYEE에서 EMP_NAME로 ASC(오름차순), DESC(내림차순) 정렬
SELECT * FROM employee ORDER BY emp_name ASC; OR DESC;
  • EMPLOYEE에서 DEPT_CODE의 오름차순, EMP_NAME의 오름차순 정렬
SELECT emp_name, dept_code FROM employee
ORDER BY dept_code ASC, emp_name ASC;

LIMIT

LIMIT 절은 MySQL에서 행수를 제어하기 위한 전용 문법으로 ANSI 비표준 문법
순서 절(ORDER BY)과 함께 사용하면 RANK를 제어하는 구문으로 사용가능
ex) 가입순으로 5명, 이름 사전순으로 5명, 나이가 많은 5명 ….

SELECT * FROM employee LIMIT 5;
SELECT emp_id, emp_name FROM employee
ORDER BY emp_name
OFFSET 5;

LIMIT + OFFSET + ORDER BY (Paging)

LIMIT + OFFSET + ORDER BY를 결합하여 Paging 처리를 수행 할 수 있다.
LIMIT는 출력되는 개수, OFFSET은 0(처음) 부터 넘어 갈 개수로 제어 할 수 있다. (OFFSET은 생략 가능)
Ex) 게시판의 페이징(Paging) 10개씩 처리 시 1page는 LIMIT 10, OFFSET 0, 2page는 LIMIT 10, OFFSET 10, 3page는 LIMIT 10, OFFSET 20 ….

SELECT * FROM employee ORDER BY emp_id LIMIT 5 OFFSET 0;
SELECT * FROM employee ORDER BY emp_id LIMIT 5 OFFSET 5;
SELECT * FROM employee ORDER BY emp_id LIMIT 5 OFFSET 10;
profile
Backend engineer

0개의 댓글