콘텐츠로 이동

데이터베이스별 SQL 차이 — 치트시트

이 튜토리얼의 SQL은 SQLite 기준으로 작성되었습니다. 각 레슨에서 MySQL/PostgreSQL 탭으로 DB별 차이를 다루고 있으므로, 이 페이지는 빠르게 훑어보는 종합 참조표 역할을 합니다.

모든 DB에서 동작하는 SQL을 작성하는 것보다, 각 DB의 네이티브 문법을 활용하는 것이 더 효율적입니다.

레슨별 DB 차이 가이드

각 레슨에서 SQLite/MySQL/PostgreSQL 탭으로 상세하게 다루는 주제입니다. 해당 레슨을 참고하세요.

주제 레슨 핵심 차이
페이징 03강 LIMIT vs FETCH FIRST (ANSI)
NULL 처리 06강 COALESCE(표준) vs IFNULL vs ISNULL vs NVL
CASE 표현식 07강 IIF(SQLite) vs IF(MySQL) vs CASE(PG)
JOIN 08~09강 문법은 동일, FULL OUTER JOIN 지원 여부
서브쿼리 10강 문법 거의 동일
날짜/시간 11강 SUBSTR vs YEAR() vs EXTRACT(), julianday vs DATEDIFF
문자열 12강 \|\| vs CONCAT(), INSTR vs LOCATE vs POSITION
숫자/변환/조건 13강 RANDOM vs RAND(), GREATEST/LEAST 지원 여부
UNION/INTERSECT/EXCEPT 14강 문법 동일, EXCEPT vs MINUS(Oracle)
DML (UPSERT) 15강 ON CONFLICT vs ON DUPLICATE KEY
DDL 16강 AUTOINCREMENT vs AUTO_INCREMENT vs GENERATED
트랜잭션 17강 BEGIN vs START TRANSACTION
윈도우 함수 18강 문법 동일, 최소 버전 차이
CTE 19강 WITH RECURSIVE(SQLite/MySQL/PG) vs WITH만(MSSQL/Oracle)
22강 CREATE OR REPLACE 지원 여부
인덱스 23강 EXPLAIN 문법, 부분 인덱스 지원
트리거 24강 SQLite: BEGIN...END, PG: 함수+트리거 분리
JSON 25강 json_extract vs ->>, JSONB(PG)
저장 프로시저 26강 SQLite 미지원, DELIMITER(MySQL), PL/pgSQL(PG)

데이터 타입 대응표

용도 SQLite MySQL PostgreSQL SQL Server Oracle
정수 INTEGER INT INTEGER INT NUMBER(10)
고정소수점 REAL DECIMAL(12,2) NUMERIC(12,2) DECIMAL(12,2) NUMBER(12,2)
부동소수점 REAL DOUBLE DOUBLE PRECISION FLOAT BINARY_DOUBLE
짧은 문자열 TEXT VARCHAR(200) VARCHAR(200) NVARCHAR(200) VARCHAR2(200)
긴 텍스트 TEXT TEXT TEXT NVARCHAR(MAX) CLOB
날짜/시간 TEXT (ISO 8601) DATETIME TIMESTAMP DATETIME2 TIMESTAMP
불리언 INTEGER (0/1) TINYINT(1) BOOLEAN BIT NUMBER(1)
JSON TEXT + json 함수 JSON JSONB NVARCHAR(MAX) CLOB
바이너리 BLOB BLOB BYTEA VARBINARY(MAX) BLOB
UUID TEXT CHAR(36) UUID UNIQUEIDENTIFIER RAW(16)

SQLite는 동적 타입 시스템을 사용합니다. 위 타입 이름은 "타입 친화도(affinity)"를 나타내며, 실제로는 어떤 값이든 저장할 수 있습니다.


식별자 인용 (Quoting)

예약어나 공백이 포함된 식별자를 감쌀 때:

DB 문법 예시
SQLite 큰따옴표 또는 백틱 "order" 또는 `order`
MySQL 백틱 (기본) `order`
PostgreSQL 큰따옴표 "order" (대소문자 구분 활성화)
SQL Server 대괄호 [order]
Oracle 큰따옴표 "ORDER" (대소문자 구분 주의)

권장

가능하면 예약어를 식별자로 사용하지 마세요. order 대신 orders, user 대신 users처럼 복수형을 쓰면 인용 부호 없이도 안전합니다.


자동 증가 비교

DB 문법 비고
SQLite INTEGER PRIMARY KEY AUTOINCREMENT ROWID 기반, AUTOINCREMENT은 선택
MySQL INT AUTO_INCREMENT PRIMARY KEY 테이블당 하나, ENGINE=InnoDB
PostgreSQL INTEGER GENERATED ALWAYS AS IDENTITY SQL 표준. SERIAL은 레거시
SQL Server INT IDENTITY(1,1) PRIMARY KEY
Oracle NUMBER GENERATED ALWAYS AS IDENTITY 12c+. 이전: SEQUENCE + TRIGGER

자세한 내용: 16강 DDL


MERGE 문

MERGE는 ANSI SQL 표준으로, 한 문장에서 INSERT/UPDATE/DELETE를 조건부로 수행합니다.

DB 지원 대체 문법
SQLite 미지원 ON CONFLICT
MySQL 미지원 ON DUPLICATE KEY UPDATE
PostgreSQL 15+ (부분) ON CONFLICT 권장
SQL Server 2008+ 완전 지원
Oracle 9i+ 완전 지원
MERGE INTO products AS target
USING staging_products AS source
ON target.sku = source.sku
WHEN MATCHED AND source.is_active = 0 THEN
    DELETE
WHEN MATCHED THEN
    UPDATE SET name = source.name, price = source.price
WHEN NOT MATCHED THEN
    INSERT (sku, name, price)
    VALUES (source.sku, source.name, source.price);
MERGE INTO products target
USING staging_products source
ON (target.sku = source.sku)
WHEN MATCHED THEN
    UPDATE SET name = source.name, price = source.price
WHEN NOT MATCHED THEN
    INSERT (sku, name, price)
    VALUES (source.sku, source.name, source.price);

UPSERT 상세: 15강 DML


기능 지원 버전 매트릭스

기능 SQLite MySQL PostgreSQL SQL Server Oracle
윈도우 함수 3.25+ 8.0+ 8.4+ 2005+ 8i+
CTE (WITH) 3.8.3+ 8.0+ 8.4+ 2005+ 11gR2+
재귀 CTE 3.8.3+ 8.0+ 8.4+ 2005+ 11gR2+
JSON 함수 3.38+ 5.7+ 9.2+ 2016+ 12c+
FULL OUTER JOIN 3.39+ 미지원 지원 지원 지원
INTERSECT/EXCEPT 3.34+ 8.0.31+ 지원 지원 지원 (MINUS)
부분 인덱스 3.8+ 미지원 지원 지원 (필터) 미지원
UPSERT 3.24+ 지원 9.5+ MERGE MERGE
저장 프로시저 미지원 지원 지원 지원 지원
트리거 지원 지원 지원 지원 지원
SEQUENCE 미지원 미지원 지원 지원 지원

튜토리얼 SQL 변환 체크리스트

이 튜토리얼의 SQLite 쿼리를 다른 DB에서 실행할 때 확인할 항목:

# 확인 사항 SQLite 원본 MySQL PostgreSQL SQL Server
1 행 제한 LIMIT 10 동일 동일 FETCH NEXT 10 ROWS ONLY
2 날짜 추출 SUBSTR(col, 1, 7) DATE_FORMAT(col, '%Y-%m') TO_CHAR(col, 'YYYY-MM') FORMAT(col, 'yyyy-MM')
3 경과 일수 JULIANDAY(a) - JULIANDAY(b) DATEDIFF(a, b) a::date - b::date DATEDIFF(DAY, b, a)
4 날짜 더하기 DATE('now', '+30 days') DATE_ADD(NOW(), INTERVAL 30 DAY) CURRENT_DATE + INTERVAL '30 days' DATEADD(DAY, 30, GETDATE())
5 NULL 대체 IFNULL(x, y) IFNULL(x, y) COALESCE(x, y) ISNULL(x, y)
6 문자열 연결 a \|\| b CONCAT(a, b) a \|\| b CONCAT(a, b)
7 불리언 is_active = 1 동일 is_active = TRUE 동일
8 타입 변환 CAST(x AS INTEGER) CAST(x AS SIGNED) x::integer CAST(x AS INT)
9 현재 시각 datetime('now') NOW() NOW() GETDATE()
10 AUTOINCREMENT INTEGER PRIMARY KEY INT AUTO_INCREMENT GENERATED ALWAYS AS IDENTITY INT IDENTITY(1,1)
11 랜덤 RANDOM() RAND() RANDOM() NEWID()
12 정규표현식 GLOB '*[0-9]*' REGEXP '[0-9]' ~ '[0-9]' LIKE '%[0-9]%'