[SQLD] Part 02 - SQL 기본 (1)

 

이 글은 내가 SQLD 자격증을 위한 공부하면서 정리하는 메모이다.


Section 01. 관계형 데이터베이스 개요

관계형 데이터베이스란

데이터를 행(Row)과 열(Column)로 이루어진 테이블로 구성하고, 테이블 간 관계로 데이터를 관리하는 데이터베이스

1970년 E.F. Codd가 제안한 모델이다. 데이터를 테이블로 표현하고, 집합 연산을 통해 원하는 데이터를 조회한다.

관계형 데이터베이스의 특징:

  • 정형화된 구조: 스키마가 미리 정의된다
  • 데이터 독립성: 내부 구조가 바뀌어도 사용자 뷰는 유지된다
  • 무결성 보장: 제약조건으로 잘못된 데이터를 막는다
  • 집합 기반 처리: 한 번에 여러 행을 처리한다

SQL이란

Structured Query Language. 관계형 데이터베이스에서 데이터를 정의하고 조작하기 위한 표준 언어

1986년 ANSI, 1987년 ISO에서 표준으로 채택되었다. Oracle, MySQL, SQL Server 등 DBMS마다 방언(dialect)이 있지만 기본 문법은 거의 같다.

SQLD는 Oracle 문법을 기준으로 출제된다.


Section 02. SQL 종류

SQL은 역할에 따라 네 가지로 분류된다.

분류 이름 설명 주요 명령어
DDL Data Definition Language 테이블 등 객체의 구조를 정의 CREATE, ALTER, DROP, RENAME, TRUNCATE
DML Data Manipulation Language 데이터를 조작 INSERT, UPDATE, DELETE, SELECT
DCL Data Control Language 접근 권한을 제어 GRANT, REVOKE
TCL Transaction Control Language 트랜잭션을 제어 COMMIT, ROLLBACK, SAVEPOINT

DCL은 SQLD 범위에서 크게 안 나온다. DDL, DML, TCL, 그리고 WHERE 절까지가 이번 파트다.


Section 03. DDL

DDL은 테이블과 같은 데이터베이스 객체의 구조를 정의하는 언어다. DDL은 자동으로 COMMIT된다. ROLLBACK이 되지 않으므로 실행 전에 신중해야 한다.

CREATE TABLE

테이블을 생성한다.

CREATE TABLE 테이블명 (
  컬럼명 데이터타입 [제약조건],
  ...
);

예:

CREATE TABLE MEMBER (
  MEMBER_ID   NUMBER        NOT NULL,
  NAME        VARCHAR2(50)  NOT NULL,
  EMAIL       VARCHAR2(100) UNIQUE,
  AGE         NUMBER        CHECK (AGE >= 0),
  STATUS      VARCHAR2(10)  DEFAULT 'ACTIVE',
  CONSTRAINT PK_MEMBER PRIMARY KEY (MEMBER_ID)
);

주요 데이터 타입

Oracle 기준 자주 나오는 데이터 타입이다.

데이터 타입 설명
NUMBER(p, s) 숫자. p: 전체 자릿수, s: 소수점 이하 자릿수
VARCHAR2(n) 가변 길이 문자열. 최대 n바이트
CHAR(n) 고정 길이 문자열. n바이트로 고정
DATE 날짜와 시간 (년/월/일/시/분/초)
CLOB 대용량 문자 데이터
BLOB 대용량 이진 데이터

VARCHAR2CHAR의 차이가 종종 나온다. CHAR(10)에 'ABC'를 저장하면 7칸이 공백으로 채워지고, VARCHAR2(10)에 저장하면 3바이트만 사용한다.

제약조건

제약조건 설명
PRIMARY KEY 기본키. NOT NULL + UNIQUE. 테이블당 하나
FOREIGN KEY 외래키. 참조 무결성 유지
UNIQUE 중복 불가. NULL은 허용
NOT NULL NULL 불가
CHECK 특정 조건 만족 여부
DEFAULT 값 미입력 시 기본값

외래키 설정:

CREATE TABLE ORDERS (
  ORDER_ID    NUMBER PRIMARY KEY,
  MEMBER_ID   NUMBER,
  ORDER_DATE  DATE,
  CONSTRAINT FK_ORDERS_MEMBER
    FOREIGN KEY (MEMBER_ID) REFERENCES MEMBER(MEMBER_ID)
);

ALTER TABLE

기존 테이블의 구조를 변경한다.

컬럼 추가

ALTER TABLE MEMBER ADD (PHONE VARCHAR2(20));

컬럼 수정

ALTER TABLE MEMBER MODIFY (NAME VARCHAR2(100));

데이터가 이미 있으면 크기를 줄이거나 타입을 바꾸는 것이 제한될 수 있다.

컬럼 삭제

ALTER TABLE MEMBER DROP COLUMN PHONE;

컬럼 이름 변경

ALTER TABLE MEMBER RENAME COLUMN STATUS TO MEMBER_STATUS;

DROP TABLE, RENAME, TRUNCATE

테이블 삭제

DROP TABLE MEMBER;

참조하는 자식 테이블이 있으면 삭제가 안 된다. CASCADE CONSTRAINTS를 붙이면 참조 제약조건까지 함께 삭제된다.

DROP TABLE MEMBER CASCADE CONSTRAINTS;

테이블 이름 변경

RENAME MEMBER TO USER_ACCOUNT;

데이터 전체 삭제 (구조 유지)

TRUNCATE TABLE ORDERS;

DELETE, TRUNCATE, DROP의 차이가 자주 출제된다.

구분 TRUNCATE DROP DELETE
분류 DDL DDL DML
ROLLBACK 불가 불가 가능
구조 유지 삭제 유지
속도 빠름 빠름 느림 (행 단위)
WHERE 사용 불가 - 사용 가능
로그 최소 없음 전체

TRUNCATE는 WHERE 절 없이 전체를 날리는데, 롤백이 안 된다는 점이 핵심이다.


Section 04. DML

DML은 테이블의 데이터를 조작하는 언어다. DDL과 달리 자동 커밋되지 않는다. COMMIT을 해야 변경이 확정된다.

INSERT

행을 삽입한다.

INSERT INTO MEMBER (MEMBER_ID, NAME, EMAIL)
VALUES (1, '홍길동', 'hong@email.com');

컬럼 목록을 생략하면 테이블 정의 순서대로 값을 입력해야 한다.

INSERT INTO MEMBER
VALUES (1, '홍길동', 'hong@email.com', 25, 'ACTIVE');

UPDATE

기존 데이터를 수정한다.

UPDATE MEMBER
SET EMAIL = 'new@email.com', AGE = 26
WHERE MEMBER_ID = 1;

WHERE 절이 없으면 전체 행이 수정된다. 항상 주의해야 한다.

DELETE

데이터를 삭제한다.

DELETE FROM MEMBER
WHERE MEMBER_ID = 1;

마찬가지로 WHERE 절이 없으면 전체 행이 삭제된다.

SELECT

데이터를 조회한다. SQL에서 가장 많이 쓰는 명령어다.

SELECT MEMBER_ID, NAME, EMAIL
FROM MEMBER;

전체 컬럼을 조회할 때는 *를 쓴다.

SELECT *
FROM MEMBER;

DISTINCT

중복된 결과를 제거한다.

SELECT DISTINCT STATUS
FROM MEMBER;

DISTINCT는 SELECT 바로 뒤에 한 번만 쓸 수 있고, 이후에 오는 모든 컬럼에 적용된다.

Alias (별칭)

컬럼이나 테이블에 임시 이름을 붙인다.

SELECT NAME AS 이름, EMAIL AS 이메일
FROM MEMBER M;
  • 컬럼 별칭: AS 키워드 사용. AS는 생략 가능
  • 별칭에 공백이 있거나 특수문자가 포함되면 큰따옴표로 감싼다
  • 테이블 별칭: FROM 절에서 테이블명 뒤에 붙임. AS 불가 (Oracle 기준)
SELECT M.NAME AS "회원 이름"
FROM MEMBER M;

Section 05. TCL

트랜잭션이란

하나의 논리적인 작업 단위. 데이터베이스에서 분리할 수 없는 최소 작업 단위

"계좌 이체"를 예로 들면, A계좌에서 출금하고 B계좌에 입금하는 두 작업이 하나의 트랜잭션이다. 둘 다 성공하거나 둘 다 실패해야 한다. 중간 상태는 허용되지 않는다.

ACID

트랜잭션이 보장해야 하는 네 가지 성질이다.

특성 이름 설명
A Atomicity (원자성) 트랜잭션은 전부 실행되거나 전혀 실행되지 않는다
C Consistency (일관성) 트랜잭션 완료 후에도 데이터베이스가 일관된 상태를 유지한다
I Isolation (고립성) 실행 중인 트랜잭션은 다른 트랜잭션의 영향을 받지 않는다
D Durability (지속성) 커밋된 트랜잭션은 장애가 발생해도 영구적으로 반영된다

COMMIT

트랜잭션의 변경 내용을 영구적으로 저장한다.

UPDATE MEMBER SET NAME = '이순신' WHERE MEMBER_ID = 1;
COMMIT;

COMMIT 이후에는 ROLLBACK으로 되돌릴 수 없다.

ROLLBACK

트랜잭션을 취소하고 이전 상태로 되돌린다.

UPDATE MEMBER SET NAME = '이순신' WHERE MEMBER_ID = 1;
ROLLBACK;

마지막 COMMIT 시점으로 되돌아간다.

SAVEPOINT

트랜잭션 중간에 저장 지점을 설정한다.

UPDATE MEMBER SET NAME = '이순신' WHERE MEMBER_ID = 1;
SAVEPOINT SP1;

UPDATE MEMBER SET AGE = 30 WHERE MEMBER_ID = 1;
SAVEPOINT SP2;

UPDATE MEMBER SET EMAIL = 'new@test.com' WHERE MEMBER_ID = 1;
ROLLBACK TO SP1;  -- SP1 이후 작업만 취소

ROLLBACK TO 저장점명으로 특정 지점까지만 취소할 수 있다.

DDL은 자동 COMMIT, DML은 명시적 COMMIT이 필요하다는 점을 헷갈리지 않아야 한다.


Section 06. WHERE 절

SELECT, UPDATE, DELETE에서 처리할 행을 필터링하는 절이다.

SELECT *
FROM MEMBER
WHERE 조건;

비교 연산자

연산자 의미
= 같다
<> 또는 != 같지 않다
> 크다
>= 크거나 같다
< 작다
<= 작거나 같다
SELECT * FROM MEMBER WHERE AGE >= 20;
SELECT * FROM MEMBER WHERE STATUS <> 'INACTIVE';

BETWEEN

범위 조건. 양 끝값을 포함한다.

SELECT * FROM MEMBER WHERE AGE BETWEEN 20 AND 30;

AGE >= 20 AND AGE <= 30과 같다. 날짜 범위 조회에도 자주 쓴다.

IN

목록 중 하나와 일치하는 조건.

SELECT * FROM MEMBER WHERE STATUS IN ('ACTIVE', 'PENDING');

STATUS = 'ACTIVE' OR STATUS = 'PENDING'과 같다.

반대는 NOT IN. 단, NULL이 포함된 목록에 NOT IN을 쓰면 결과가 빈 집합이 될 수 있어서 주의해야 한다.

LIKE

패턴 매칭.

와일드카드 의미
% 0개 이상의 임의 문자
_ 1개의 임의 문자
SELECT * FROM MEMBER WHERE NAME LIKE '김%';           -- 김으로 시작
SELECT * FROM MEMBER WHERE EMAIL LIKE '%@gmail.com';  -- gmail.com으로 끝남
SELECT * FROM MEMBER WHERE NAME LIKE '김_수';         -- 김으로 시작하고 수로 끝나는 세 글자

IS NULL / IS NOT NULL

NULL 여부 확인.

SELECT * FROM MEMBER WHERE EMAIL IS NULL;
SELECT * FROM MEMBER WHERE EMAIL IS NOT NULL;

NULL은 = NULL로 비교하면 안 된다. = NULL의 결과는 항상 FALSE다. 반드시 IS NULL을 써야 한다.

논리 연산자

연산자 설명
AND 두 조건 모두 참
OR 두 조건 중 하나 이상 참
NOT 조건을 부정
SELECT * FROM MEMBER
WHERE AGE >= 20 AND STATUS = 'ACTIVE';

SELECT * FROM MEMBER
WHERE STATUS = 'INACTIVE' OR AGE < 18;

SELECT * FROM MEMBER
WHERE NOT STATUS = 'ACTIVE';

연산자 우선순위

우선순위가 헷갈리면 결과가 달라질 수 있다. 중요한 것만 기억하면 된다.

높음  1. 산술 연산자 (+, -, *, /)
      2. 비교 연산자 (=, <>, >, <, >=, <=)
      3. NOT
      4. AND
낮음  5. OR

AND가 OR보다 우선순위가 높다는 것이 핵심이다.

-- 의도: (STATUS = 'ACTIVE' OR STATUS = 'PENDING') AND AGE >= 20
-- 실제: STATUS = 'ACTIVE' OR (STATUS = 'PENDING' AND AGE >= 20)
WHERE STATUS = 'ACTIVE' OR STATUS = 'PENDING' AND AGE >= 20

괄호로 명확하게 표현하는 것이 좋다.

WHERE (STATUS = 'ACTIVE' OR STATUS = 'PENDING') AND AGE >= 20

 

 

'Study > SQL' 카테고리의 다른 글

[SQLD] Part 03 - SQL 기본 (2)  (0) 2026.03.14
[SQLD] Part 01 - 데이터 모델링  (1) 2026.03.03