SQL(Structured Query Language)은 관계형 데이터베이스 관리 시스템(RDBMS)의 데이터를 관리하기 위해 설계한 특수 목적의 프로그래밍 언어이다
DDL(Data Definition Language) : 데이터베이스 구조 정의에 사용하는 언어
객체 생성 명령어
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(255) UNIQUE,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='회원 정보 테이블';
column options
| 옵션 | 설명 |
|---|---|
NOT NULL | NULL 허용 안 함 |
NULL | NULL 허용 |
DEFAULT 값 | 기본값 지정 |
AUTO_INCREMENT | 자동 증가 |
UNIQUE | 유일값 제약 |
PRIMARY KEY | 기본 키 지정 |
COMMENT '설명' | 컬럼 주석 |
CHECK (조건) | 제약 조건 (MySQL 8.0 이상) |
GENERATED ALWAYS AS (...) STORED | 생성된 컬럼 (계산된 값 저장) |
table options
| 옵션 | 설명 |
|---|---|
ENGINE=InnoDB | 스토리지 엔진 지정 |
DEFAULT CHARSET=utf8mb4 | 문자셋 지정 |
COLLATE=utf8mb4_unicode_ci | 정렬 방식 지정 |
COMMENT='테이블 설명' | 테이블 주석 |
AUTO_INCREMENT=1000 | 자동 증가 시작 값 |
CREATE UNIQUE INDEX idx_email ON users(email) USING BTREE;
options
| 옵션 | 설명 |
|---|---|
UNIQUE | 유일한 값만 허용되는 인덱스 생성 |
USING BTREE | 인덱스 알고리즘 지정 (BTREE, HASH 등) |
VISIBLE / INVISIBLE | 인덱스 사용 여부 제어 (8.0 이상) |
CREATE ALGORITHM=MERGE SQL SECURITY DEFINER VIEW user_view AS
SELECT * FROM users WHERE is_active = 1
WITH CHECK OPTION;
options
| 옵션 | 설명 |
|---|---|
ALGORITHM | 뷰 생성 알고리즘 지정 (UNDEFINED, MERGE, TEMPTABLE) |
DEFINER | 뷰 생성자 명시 (DEFINER = 'user'@'host') |
SQL SECURITY | 권한 설정 (DEFINER 또는 INVOKER) |
WITH CHECK OPTION | 수정 시 WHERE 조건 강제 |
CREATE TRIGGER trg_users_insert
BEFORE INSERT ON users
FOR EACH ROW
SET NEW.created_at = NOW();
options
| 옵션 | 설명 |
|---|---|
BEFORE / AFTER | 트리거 실행 시점 지정 |
INSERT/UPDATE/DELETE | 작동할 DML 종류 지정 |
FOR EACH ROW | 행 단위 트리거 |
CREATE SEQUENCE user_seq
START WITH 1000 INCREMENT BY 1 CYCLE;
options
| 옵션 | 설명 |
|---|---|
START WITH | 시작값 |
INCREMENT BY | 증가값 |
MINVALUE / MAXVALUE | 최소/최대값 |
CYCLE / NO CYCLE | 값이 최대 도달 시 재순환 여부 |
CACHE | 메모리에 미리 저장할 숫자 수 |
CREATE TABLE users (
id NUMBER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name VARCHAR2(100) NOT NULL,
email VARCHAR2(255) UNIQUE,
created_at DATE DEFAULT SYSDATE,
full_name VARCHAR2(255) GENERATED ALWAYS AS (name || ' ' || email) VIRTUAL
) TABLESPACE userspace LOGGING;
column options
| 옵션 | 설명 |
|---|---|
NOT NULL | NULL 허용 안 함 |
DEFAULT 값 | 기본값 지정 |
UNIQUE | 유일값 제약 |
PRIMARY KEY | 기본 키 지정 |
CHECK (조건) | 제약 조건 |
GENERATED ALWAYS AS IDENTITY | 자동 증가 컬럼 (Oracle 12c 이상) |
INVISIBLE | 기본적으로 SELECT 시 보이지 않게 설정 |
VIRTUAL or STORED | 계산된 컬럼 설정 |
table options
| 옵션 | 설명 |
|---|---|
TABLESPACE | 저장할 테이블스페이스 지정 |
PCTFREE, PCTUSED | 블록 내 여유공간 관리 |
INITRANS, MAXTRANS | 동시 트랜잭션 수 설정 |
LOGGING / NOLOGGING | 로깅 여부 설정 |
COMPRESS / NOCOMPRESS | 데이터 압축 설정 |
ENABLE ROW MOVEMENT | 파티션 간 행 이동 허용 |
CREATE UNIQUE INDEX idx_email ON users(email) TABLESPACE indexspace;
options
| 옵션 | 설명 |
|---|---|
UNIQUE | 유일한 값만 허용되는 인덱스 생성 |
TABLESPACE | 인덱스를 저장할 테이블스페이스 지정 |
NOPARALLEL / PARALLEL | 병렬 인덱스 생성 여부 |
COMPRESS | 인덱스 압축 |
CREATE VIEW active_users AS
SELECT * FROM users WHERE is_active = 1
WITH CHECK OPTION;
options
| 옵션 | 설명 |
|---|---|
WITH CHECK OPTION | INSERT/UPDATE 시 조건 강제 |
WITH READ ONLY | 뷰를 읽기 전용으로 설정 |
CREATE OR REPLACE TRIGGER trg_users_insert
BEFORE INSERT ON users
FOR EACH ROW
BEGIN
:NEW.created_at := SYSDATE;
END;
options
| 옵션 | 설명 |
|---|---|
BEFORE / AFTER | 트리거 실행 시점 |
INSERT/UPDATE/DELETE | 작동할 DML 지정 |
FOR EACH ROW | 행 단위 트리거 |
WHEN (조건) | 특정 조건일 때만 작동 |
CREATE SEQUENCE user_seq
START WITH 1000 INCREMENT BY 1 NOCACHE NOCYCLE;
options
| 옵션 | 설명 |
|---|---|
START WITH | 시작값 |
INCREMENT BY | 증가값 |
MINVALUE / MAXVALUE | 최소/최대값 |
CYCLE / NOCYCLE | 값이 최대 도달 시 재순환 여부 |
CACHE / NOCACHE | 메모리 캐싱 여부 |
ORDER / NOORDER | 순서 보장 여부 |
객체 구조 변경 명령어
ALTER TABLE users ADD COLUMN age INT;
ALTER TABLE users MODIFY COLUMN name VARCHAR(200);
ALTER TABLE users CHANGE COLUMN email email_address VARCHAR(255);
ALTER TABLE users DROP COLUMN age;
ALTER TABLE users RENAME TO members;
| 구문 종류 | 설명 |
|---|---|
ADD COLUMN | 새로운 컬럼 추가 |
DROP COLUMN | 컬럼 삭제 |
MODIFY COLUMN | 기존 컬럼의 타입/속성 변경 |
CHANGE COLUMN | 컬럼 이름 및 속성 변경 |
RENAME COLUMN | 컬럼 이름 변경 (MySQL 8.0 이상) |
RENAME TO | 테이블 이름 변경 |
ADD CONSTRAINT | 제약 조건 추가 (PRIMARY KEY, FOREIGN KEY) |
DROP PRIMARY KEY | 기본 키 삭제 |
DROP FOREIGN KEY | 외래 키 삭제 |
ADD INDEX, ADD UNIQUE | 인덱스 추가 |
DROP INDEX | 인덱스 삭제 |
ALTER COLUMN ... SET DEFAULT | 기본값 설정 |
ALTER COLUMN ... DROP DEFAULT | 기본값 제거 |
CONVERT TO CHARACTER SET | 문자셋 변경 |
ALTER TABLE users ADD age NUMBER;
ALTER TABLE users MODIFY name VARCHAR2(200);
ALTER TABLE users RENAME COLUMN email TO email_address;
ALTER TABLE users RENAME TO members;
ALTER TABLE users ADD CONSTRAINT pk_users PRIMARY KEY (id);
ALTER TABLE users DROP CONSTRAINT pk_users;
| 구문 종류 | 설명 |
|---|---|
ADD | 새로운 컬럼 추가 |
DROP COLUMN | 컬럼 삭제 |
MODIFY | 컬럼의 데이터 타입, 제약 조건 변경 |
RENAME COLUMN ... TO | 컬럼 이름 변경 (Oracle 12c 이상) |
RENAME TO | 테이블 이름 변경 |
ADD CONSTRAINT | 제약 조건 추가 (PRIMARY KEY, FOREIGN KEY 등) |
DROP CONSTRAINT | 제약 조건 삭제 |
ENABLE / DISABLE CONSTRAINT | 제약 조건 활성/비활성 |
SET UNUSED / DROP UNUSED COLUMNS | 컬럼 논리적 제거 |
ALTER COLUMN ... SET DEFAULT | 기본값 설정 |
ALTER COLUMN ... DROP DEFAULT | 기본값 제거 |
MOVE TABLESPACE | 테이블을 다른 테이블스페이스로 이동 |
| 기능 | MySQL | Oracle |
|---|---|---|
| 이름 변경 | ALTER TABLE DROP INDEX + ADD INDEX 조합 사용 | ALTER INDEX index_name RENAME TO new_name |
| 재생성 | 직접 삭제 후 재생성 필요 | ALTER INDEX index_name REBUILD |
| 비활성화/활성화 | 없음 | ALTER INDEX index_name UNUSABLE |
| 저장 위치 변경 | 없음 | ALTER INDEX index_name REBUILD TABLESPACE ts |
| 기능 | MySQL | Oracle |
|---|---|---|
| 뷰 정의 수정 | CREATE OR REPLACE VIEW 사용 | CREATE OR REPLACE VIEW 사용 |
| 읽기 전용 설정 | WITH READ ONLY 포함하여 다시 정의 | WITH READ ONLY 포함하여 다시 정의 |
| 권한 변경 | GRANT, REVOKE 명령으로 처리 | GRANT, REVOKE 명령으로 처리 |
| 직접 ALTER 명령어 | ❌ 없음 | ❌ 없음 |
| 기능 | MySQL | Oracle |
|---|---|---|
| 트리거 수정 | 삭제 후 재생성 필요 | ALTER TRIGGER trigger_name 문법 사용 가능 |
| 활성/비활성화 | ❌ 지원 안 함 (삭제 후 재생성 필요) | ENABLE / DISABLE 지원 |
| 이름 변경 | ❌ 직접 불가 | ❌ 직접 불가 (삭제 후 재생성 필요) |
| 기능 | MySQL (8.0 이상) | Oracle |
|---|---|---|
| 시작값/증가값 변경 | ALTER SEQUENCE 일부 지원 | ALTER SEQUENCE 완전 지원 |
| 캐시 설정 | CACHE, NOCACHE 등 지원 | CACHE, NOCACHE, CYCLE, NOCYCLE 등 완전 지원 |
| 재시작 | RESTART WITH 사용 가능 | START WITH 변경 불가 → 새로 만들어야 함 |
객체 삭제 명령어
| 객체 종류 | 문법 예시 | 설명 |
|---|---|---|
| TABLE | DROP TABLE users; | 테이블 삭제 |
| IF EXISTS | DROP TABLE IF EXISTS users; | 존재할 때만 삭제 |
| VIEW | DROP VIEW active_users; | 뷰 삭제 |
| INDEX | DROP INDEX idx_name ON users; | 인덱스 삭제 (테이블 이름 필요) |
| TRIGGER | DROP TRIGGER trg_users_insert; | 트리거 삭제 |
| SEQUENCE | DROP SEQUENCE user_seq; | 시퀀스 삭제 (MySQL 8.0 이상) |
| DATABASE | DROP DATABASE shopdb; | 데이터베이스 전체 삭제 |
| USER | DROP USER 'user'@'localhost'; | 사용자 삭제 |
| 객체 종류 | 문법 예시 | 설명 |
|---|---|---|
| TABLE | DROP TABLE users; | 테이블 삭제 |
| PURGE 옵션 | DROP TABLE users PURGE; | 휴지통(RECYCLEBIN) 건너뛰고 완전 삭제 |
| VIEW | DROP VIEW active_users; | 뷰 삭제 |
| INDEX | DROP INDEX idx_name; | 인덱스 삭제 |
| TRIGGER | DROP TRIGGER trg_users_insert; | 트리거 삭제 |
| SEQUENCE | DROP SEQUENCE user_seq; | 시퀀스 삭제 |
| USER | DROP USER shop_user CASCADE; | 사용자 및 그 소유 객체 모두 삭제 |
| SYNONYM | DROP SYNONYM syn_name; | 시노님 삭제 |
| TYPE | DROP TYPE object_type_name; | 사용자 정의 타입 삭제 |
테이블 데이터 전체 삭제 명령어
* MySQL, Oracle 동일
TRUNCATE TABLE table_name;
객체 이름 변경 명령어
RENAME TABLE users TO customers;
ALTER TABLE users RENAME COLUMN email TO email_address;
| 대상 | 문법 예시 | 설명 |
|---|---|---|
| 테이블 | RENAME TABLE old_name TO new_name; | 테이블 이름 변경 |
| 여러 테이블 | RENAME TABLE a TO b, c TO d; | 여러 개 테이블 이름 한번에 변경 가능 |
| 컬럼 | ALTER TABLE tbl RENAME COLUMN old TO new; | 컬럼 이름 변경 (MySQL 8.0 이상) |
| 데이터베이스 | ❌ 직접 RENAME 불가 (백업 후 생성 필요) | |
| 뷰 | RENAME TABLE view_name TO new_view; | 뷰도 테이블처럼 이름 변경 가능 |
RENAME users TO customers;
ALTER TABLE users RENAME COLUMN email TO email_address;
| 대상 | 문법 예시 | 설명 |
|---|---|---|
| 테이블 | RENAME old_name TO new_name; | 테이블 이름 변경 |
| 컬럼 | ALTER TABLE tbl RENAME COLUMN old TO new; | 컬럼 이름 변경 (12c 이상 지원) |
| 시노님(SYNONYM) | RENAME old_syn TO new_syn; | 시노님 이름 변경 |
| 인덱스 | ❌ 직접 RENAME 불가 (ALTER INDEX ... RENAME TO) 사용 | |
| 시퀀스 | ❌ 직접 RENAME 불가 (DROP + CREATE 필요) | |
| 뷰 | RENAME view_name TO new_view; | 뷰 이름 변경 |
객체 주석 추가 명령어
* MySQL은 CREATE 시에 주석을 추가한다
Oracle
COMMENT ON TABLE users IS '회원 정보를 저장하는 테이블';
COMMENT ON COLUMN users.name IS '사용자 이름';
| 대상 | 문법 예시 | 설명 |
|---|---|---|
| 테이블 | COMMENT ON TABLE users IS '유저 테이블'; | 테이블에 주석 달기 |
| 컬럼 | COMMENT ON COLUMN users.email IS '이메일 주소'; | 컬럼에 주석 달기 |
| 뷰 | COMMENT ON TABLE active_users IS '활성 사용자 뷰'; | 뷰도 테이블처럼 작성 |
| 항목 | TRUNCATE | DELETE | DROP |
|---|---|---|---|
| 데이터 삭제만 | ✅ | ✅ | ❌ (구조까지 삭제) |
| 테이블 구조 유지 | ✅ | ✅ | ❌ |
| 롤백 가능 여부 | ❌ (Oracle: DDL로 취급, 자동 커밋) | ✅ (트랜잭션 안에서 사용 가능) | ❌ |
| WHERE 절 사용 가능 | ❌ | ✅ | ❌ |
| 속도 | 🔥 빠름 | 느림 (로그 기록됨) | 가장 빠름 (전체 제거) |
| 트리거 작동 | ❌ 작동안함 | ✅ 작동 | ❌ (트리거 대상 없음) |
| 제약 조건 검사 | ❌ (제한적 적용) | ✅ | ❌ |
DML(Data Manipulation Language) : 데이터 조작에 사용하는 언어
데이터를 조회할 때 사용하는 명령어
-- 모든 컬럼 조회
SELECT * FROM users;
-- 특정 컬럼 조회
SELECT name, email FROM users;
-- 조건으로 필터링
SELECT name, email FROM users WHERE age > 30;
-- 정렬
SELECT * FROM users ORDER BY name DESC;
-- 개수 제한
SELECT * FROM users LIMIT 10;
-- 모든 컬럼 조회
SELECT * FROM users;
-- 특정 컬럼 조회
SELECT name, email FROM users;
-- 조건으로 필터링
SELECT name, email FROM users WHERE age > 30;
-- 정렬
SELECT * FROM users ORDER BY name DESC;
-- 개수 제한 (Oracle 12c 이상에서는 `FETCH FIRST` 사용)
SELECT * FROM users FETCH FIRST 10 ROWS ONLY;
| 항목 | MySQL | Oracle |
|---|---|---|
| 결과 개수 제한 | LIMIT 사용 | ROWNUM, FETCH FIRST 사용 |
| 조인 | JOIN 지원 (INNER, LEFT, RIGHT 등) | JOIN 지원 (INNER, LEFT, RIGHT 등) |
| 정렬 | ORDER BY | ORDER BY |
| 집합 함수 | COUNT(), AVG(), MAX(), MIN(), SUM() | 동일 |
| 문자열 연산 | CONCAT() 함수 사용 | || 연산자 또는 CONCAT() 함수 사용 |
GROUP BY + HAVING | 동일 | 동일 |
데이터를 테이블에 추가할 때 사용하는 명령어
INSERT INTO table_name (column1, column2, ...)
VALUES (value1, value2, ...);
-- 다중 행 INSERT
INSERT INTO users (name, email)
VALUES
('Charlie', 'charlie@example.com'),
('David', 'david@example.com'),
('Eve', 'eve@example.com');
-- UPSERT : 없으면 INSERT 있으면 UPDATE
INSERT INTO users (id, name, email)
VALUES (1, 'Alice', 'alice@example.com')
ON DUPLICATE KEY UPDATE name = 'Updated Name';
-- 오류 발생 시 무시하고 진행
INSERT IGNORE INTO users (id, name, email)
VALUES (1, 'Alice', 'alice@example.com');
INSERT INTO table_name (column1, column2, ...)
VALUES (value1, value2, ...);
-- 다중 행 INSERT
INSERT ALL
INTO users (name, email) VALUES ('Charlie', 'charlie@example.com')
INTO users (name, email) VALUES ('David', 'david@example.com')
INTO users (name, email) VALUES ('Eve', 'eve@example.com')
SELECT * FROM dual;
-- UPSERT
MERGE INTO users u
USING (SELECT 1 AS id, 'Alice' AS name, 'alice@example.com' AS email FROM dual) src
ON (u.id = src.id)
WHEN MATCHED THEN
UPDATE SET u.name = src.name, u.email = src.email
WHEN NOT MATCHED THEN
INSERT (id, name, email) VALUES (src.id, src.name, src.email);
-- 자동 증가 컬럼 처리
INSERT INTO users (id, name, email)
VALUES (user_seq.NEXTVAL, 'Frank', 'frank@example.com');
MySQL, Oracle 둘 다 다른 테이블 데이터를 조회하여 삽입할 수 있다
INSERT INTO users (name, email)
SELECT name, email FROM new_users WHERE active = 1;
기존 데이터를 수정할 때 사용하는 명령어
UPDATE table_name
SET column1 = value1, column2 = value2, ...
WHERE condition;
| 항목 | MySQL | Oracle |
|---|---|---|
| 기본 UPDATE 문법 | UPDATE ... SET ... WHERE ... | 동일 |
| JOIN을 활용한 업데이트 | UPDATE ... JOIN ... 가능 | MERGE INTO 또는 UPDATE + EXISTS 활용 필요 |
| 다중 테이블 업데이트 | UPDATE t1, t2 SET ... WHERE ... 가능 | 불가능 (단일 테이블만 가능) |
| 서브쿼리 활용 가능 여부 | 가능 | 가능 |
| UPSERT 지원 | ON DUPLICATE KEY UPDATE | MERGE INTO 사용 |
데이터를 삭제할 때 사용하는 명령어
DELETE FROM table_name
WHERE condition;
| 항목 | MySQL | Oracle |
|---|---|---|
| 기본 문법 | DELETE FROM table WHERE ... | 동일 |
| 조건 없는 전체 삭제 | 가능 (DELETE FROM table) | 가능 (DELETE FROM table) |
| JOIN 기반 삭제 | DELETE FROM t1 USING ... JOIN ... | EXISTS, IN 사용 |
| 다중 테이블 삭제 | 가능 (DELETE t1, t2 FROM ...) | 불가능 (한 번에 하나만) |
| 트랜잭션 처리 | 지원 (START TRANSACTION, ROLLBACK) | 지원 (BEGIN, SAVEPOINT, ROLLBACK) |
DCL(Data Control Language) : 데이터베이스 접근 권한 제어에 사용하는 언어
사용자에게 권한을 부여할 때 사용하는 명령어
GRANT privileges
ON database_name.table_name
TO 'username'@'host'
[WITH GRANT OPTION];
GRANT privileges
TO username
[WITH GRANT OPTION];
| 항목 | MySQL | Oracle |
|---|---|---|
| 기본 문법 | GRANT ... ON db.table TO 'user'@'host' | GRANT ... TO username |
| 대상 지정 방식 | 'user'@'host' | username (DB 계정) |
| 시스템 권한 | 일부 가능 (GRANT ALL PRIVILEGES, etc.) | 명시적 (CREATE SESSION, CREATE TABLE, etc.) |
| 객체 권한 | 테이블, DB, 뷰, 프로시저 등에 권한 부여 가능 | 테이블, 뷰, 시퀀스 등 개별 객체에 권한 부여 |
| 권한 위임 (전가) | WITH GRANT OPTION | WITH GRANT OPTION |
| 역할(Role) 사용 | MySQL 8.0 이상에서 지원 | 역할(Role) 시스템 내장됨 (CONNECT, RESOURCE, 등) |
| 권한 확인 방법 | SHOW GRANTS FOR 'user'@'host' | USER_TAB_PRIVS, ALL_TAB_PRIVS, DBA_TAB_PRIVS 등 조회 |
사용자에게 권한을 회수할 때 사용하는 명령어
REVOKE privileges
ON database_name.table_name
FROM 'username'@'host';
REVOKE privileges
ON object_name
FROM username;
| 항목 | MySQL | Oracle |
|---|---|---|
| 기본 문법 | REVOKE ... ON db.table FROM 'user'@'host' | REVOKE ... ON object FROM user |
| 시스템 권한 회수 | REVOKE ALL PRIVILEGES 포함 | REVOKE CREATE SESSION, CREATE TABLE 등 |
| 객체 권한 회수 | 테이블, 뷰, 프로시저 등 | 테이블, 뷰, 시퀀스 등 |
| 역할(Role) 회수 | REVOKE 'role' FROM 'user'@'host' (8.0 이상) | REVOKE role FROM user |
| 권한 위임 제거 | REVOKE GRANT OPTION FOR ... 가능 (제한적) | REVOKE ... WITH GRANT OPTION도 제거됨 |
TCL(Transaction Control Language) : 트랜잭션을 제어할 때 사용하는 언어. DCL로 분류되기도 한다
| 항목 | MySQL | Oracle |
|---|---|---|
| 트랜잭션 시작 | START TRANSACTION, BEGIN 필요 | DML 수행 시 자동 시작 |
| COMMIT | 변경 사항 영구 반영 | 동일 |
| ROLLBACK | 변경 사항 모두 취소 | 동일 |
| SAVEPOINT | 중간 지점 설정 가능 | 동일 |
| ROLLBACK TO SAVEPOINT | 저장점까지 부분 롤백 | 동일 |
| 자동 커밋 | 기본적으로 비활성화 (autocommit=0 설정 시) | 대부분의 클라이언트에서 자동커밋 OFF |
| 격리 수준 설정 | SET TRANSACTION ISOLATION LEVEL ... | 동일 |