PostgreSQL의 데이터베이스, 스키마, 테이블 생성 및 관리 방법을 정리합니다.

데이터베이스 관리

데이터베이스 생성

-- 기본 생성
CREATE DATABASE mydb;

-- 옵션 지정
CREATE DATABASE mydb
  OWNER = devuser
  ENCODING = 'UTF8'
  LC_COLLATE = 'ko_KR.UTF-8'
  LC_CTYPE = 'ko_KR.UTF-8'
  TEMPLATE = template0;

-- 이미 존재하면 무시 (PostgreSQL 9.5+에서는 IF NOT EXISTS 미지원, 대안)
SELECT 'CREATE DATABASE mydb' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = 'mydb')\gexec

데이터베이스 조회 및 삭제

-- 데이터베이스 목록
\l
SELECT datname, datdba, encoding, datcollate FROM pg_database;

-- 현재 데이터베이스 확인
SELECT current_database();

-- 데이터베이스 전환 (psql)
\c mydb

-- 데이터베이스 삭제 (접속 중인 세션이 없어야 함)
DROP DATABASE mydb;
DROP DATABASE IF EXISTS mydb;

스키마 (Schema)

PostgreSQL의 스키마는 데이터베이스 내의 네임스페이스입니다.
MySQL에서는 Database가 이 역할을 하지만, PostgreSQL은 Database > Schema > Table 3단계 구조입니다.

-- 스키마 생성
CREATE SCHEMA app;
CREATE SCHEMA IF NOT EXISTS app;

-- 스키마 목록
\dn
SELECT schema_name FROM information_schema.schemata;

-- 검색 경로 설정 (스키마명 생략 시 탐색 순서)
SET search_path TO app, public;
SHOW search_path;

-- 스키마 삭제
DROP SCHEMA app;
DROP SCHEMA app CASCADE;  -- 포함된 객체 모두 삭제

스키마 활용 예시

-- 스키마별 테이블 분리
CREATE SCHEMA sales;
CREATE SCHEMA hr;

CREATE TABLE sales.orders (id SERIAL PRIMARY KEY, amount NUMERIC);
CREATE TABLE hr.employees (id SERIAL PRIMARY KEY, name VARCHAR(50));

-- 스키마 지정 조회
SELECT * FROM sales.orders;
SELECT * FROM hr.employees;

테이블 관리

테이블 생성

CREATE TABLE employees (
    id          SERIAL          PRIMARY KEY,
    name        VARCHAR(50)     NOT NULL,
    email       VARCHAR(100)    NOT NULL UNIQUE,
    dept_id     INTEGER,
    salary      NUMERIC(12,2)   DEFAULT 0,
    is_active   BOOLEAN         DEFAULT TRUE,
    hire_date   DATE            DEFAULT CURRENT_DATE,
    created_at  TIMESTAMPTZ     DEFAULT NOW(),
    updated_at  TIMESTAMPTZ     DEFAULT NOW()
);

-- 테이블 코멘트
COMMENT ON TABLE employees IS '직원 정보 테이블';
COMMENT ON COLUMN employees.id IS '직원 고유 ID';
COMMENT ON COLUMN employees.salary IS '급여 (원)';

주요 데이터 타입

숫자형

타입 크기 범위 MySQL 대응
SMALLINT 2byte -32,768 ~ 32,767 SMALLINT
INTEGER (INT) 4byte -21억 ~ 21억 INT
BIGINT 8byte -922경 ~ 922경 BIGINT
NUMERIC(p,s) 가변 정밀 소수 DECIMAL
REAL 4byte 6자리 정밀도 FLOAT
DOUBLE PRECISION 8byte 15자리 정밀도 DOUBLE
SERIAL 4byte 자동 증가 정수 AUTO_INCREMENT
BIGSERIAL 8byte 자동 증가 큰 정수 BIGINT AUTO_INCREMENT

문자형

타입 설명 MySQL 대응
VARCHAR(n) 가변 길이 (최대 n자) VARCHAR
CHAR(n) 고정 길이 CHAR
TEXT 무제한 가변 길이 LONGTEXT

PostgreSQL에서는 VARCHARTEXT의 성능 차이가 없습니다. TEXT를 자유롭게 사용해도 됩니다.

날짜/시간형

타입 설명 MySQL 대응
DATE 날짜만 DATE
TIME 시간만 TIME
TIMESTAMP 날짜+시간 (시간대 없음) DATETIME
TIMESTAMPTZ 날짜+시간 (시간대 포함, 권장) TIMESTAMP
INTERVAL 시간 간격 없음

PostgreSQL 고유 타입

타입 설명
BOOLEAN true/false
UUID 범용 고유 식별자
JSONB 바이너리 JSON (인덱싱 가능, 권장)
JSON 텍스트 JSON
ARRAY 배열 (INTEGER[], TEXT[] 등)
HSTORE 키-값 쌍
INET / CIDR IP 주소 / 네트워크
POINT / LINE / POLYGON 기하학 타입
TSVECTOR 전문 검색용
BYTEA 바이너리 데이터

테이블 조회

-- 테이블 목록
\dt
\dt app.*   -- 특정 스키마

-- 테이블 구조
\d employees
\d+ employees   -- 상세 (코멘트 포함)

-- 테이블 DDL 추출 (pg_dump 사용)
-- pg_dump -U postgres -d mydb -t employees --schema-only

테이블 수정 (ALTER TABLE)

-- 컬럼 추가
ALTER TABLE employees ADD COLUMN phone VARCHAR(20);

-- 컬럼 타입 변경
ALTER TABLE employees ALTER COLUMN phone TYPE VARCHAR(30);

-- NOT NULL 추가/제거
ALTER TABLE employees ALTER COLUMN phone SET NOT NULL;
ALTER TABLE employees ALTER COLUMN phone DROP NOT NULL;

-- 기본값 설정/제거
ALTER TABLE employees ALTER COLUMN salary SET DEFAULT 3000000;
ALTER TABLE employees ALTER COLUMN salary DROP DEFAULT;

-- 컬럼 이름 변경
ALTER TABLE employees RENAME COLUMN phone TO mobile;

-- 컬럼 삭제
ALTER TABLE employees DROP COLUMN mobile;

-- 테이블 이름 변경
ALTER TABLE employees RENAME TO members;
ALTER TABLE members RENAME TO employees;

테이블 삭제

DROP TABLE employees;
DROP TABLE IF EXISTS employees;
DROP TABLE employees CASCADE;  -- 의존 객체 함께 삭제

-- 데이터만 삭제 (구조 유지)
TRUNCATE TABLE employees;
TRUNCATE TABLE employees RESTART IDENTITY;  -- SERIAL 리셋
TRUNCATE TABLE employees CASCADE;           -- FK 참조 테이블도 함께

제약 조건 (Constraints)

제약 조건 설명 예시
PRIMARY KEY 기본키 id SERIAL PRIMARY KEY
UNIQUE 중복 불가 email VARCHAR(100) UNIQUE
NOT NULL NULL 불가 name VARCHAR(50) NOT NULL
CHECK 값 범위 제한 CHECK (salary >= 0)
FOREIGN KEY 외래키 참조 아래 예시 참고
DEFAULT 기본값 salary NUMERIC DEFAULT 0
EXCLUDE 범위 겹침 방지 (PostgreSQL 전용) GiST 인덱스 활용

외래키 설정

CREATE TABLE orders (
    id          SERIAL PRIMARY KEY,
    emp_id      INTEGER NOT NULL,
    product     VARCHAR(100) NOT NULL,
    amount      NUMERIC(12,2) NOT NULL,
    ordered_at  TIMESTAMPTZ DEFAULT NOW(),
    CONSTRAINT fk_orders_emp FOREIGN KEY (emp_id)
        REFERENCES employees(id)
        ON DELETE CASCADE
        ON UPDATE CASCADE
);

제약 조건 관리

-- 제약 조건 조회
SELECT conname, contype, conrelid::regclass
FROM pg_constraint
WHERE conrelid = 'employees'::regclass;

-- 제약 조건 추가
ALTER TABLE employees ADD CONSTRAINT ck_salary CHECK (salary >= 0);

-- 제약 조건 삭제
ALTER TABLE employees DROP CONSTRAINT ck_salary;

관련된 글 (postgresql > lecture-postgresql)