PostgreSQL 치트시트
검색과 인쇄가 가능한 PostgreSQL 참고자료입니다: psql 명령어, JSONB, 배열, CTE, 윈도우 함수, 인덱스, 역할, EXPLAIN까지. 무료입니다.
psql meta-commands
15psql -U user -d mydb -h localhost
\l
\c mydb
\dt
\d users
\d+ users
\dn
\df
\du
\x
\timing
\e
\i script.sql
\copy users TO 'users.csv' CSV HEADER
\q
Querying
10SELECT * FROM users LIMIT 10;
WHERE name ILIKE '%ann%'
WHERE name ~* '^a.*z$'
ORDER BY score DESC NULLS LAST
SELECT DISTINCT ON (user_id) * FROM orders ORDER BY user_id, created_at DESC;
LIMIT 10 OFFSET 20
FETCH FIRST 5 ROWS ONLY
SELECT ... FOR UPDATE SKIP LOCKED
TABLESAMPLE SYSTEM (1)
LATERAL (SELECT ... LIMIT 3)
JSONB
14data->'user'
data->>'name'
data#>>'{user,address,city}'
data @> '{"active": true}'
data ? 'email'
data ?| array['a', 'b']
jsonb_set(data, '{name}', '"Sam"')
data - 'legacy_field'
data || '{"active": true}'
jsonb_array_elements(data->'items')
jsonb_each(data)
jsonb_build_object('id', id, 'name', name)
jsonb_agg(row_to_json(t))
jsonb_pretty(data)
Arrays & ranges
13tags TEXT[]
ARRAY['a', 'b', 'c']
tags[1]
WHERE 'php' = ANY(tags)
WHERE tags @> ARRAY['php','sql']
WHERE tags && ARRAY['php','go']
array_agg(name ORDER BY name)
unnest(tags)
array_length(tags, 1)
string_to_array('a,b', ',')
period tstzrange
WHERE period @> now()
EXCLUDE USING gist (room WITH =, period WITH &&)
CTEs & window functions
12WITH recent AS (SELECT ...) SELECT * FROM recent;
WITH RECURSIVE tree AS (... UNION ALL ...)
WITH del AS (DELETE ... RETURNING *) INSERT ...
ROW_NUMBER() OVER (ORDER BY score DESC)
RANK() / DENSE_RANK() OVER (...)
OVER (PARTITION BY user_id ORDER BY at)
LAG(price) OVER (ORDER BY day)
LEAD(price, 2) OVER (...)
SUM(amount) OVER (ORDER BY day)
AVG(x) OVER (ROWS BETWEEN 6 PRECEDING AND CURRENT ROW)
NTILE(4) OVER (ORDER BY score)
FIRST_VALUE(name) OVER (...)
Upsert & RETURNING
9INSERT ... ON CONFLICT (email) DO UPDATE SET name = EXCLUDED.name;
ON CONFLICT DO NOTHING
ON CONFLICT ON CONSTRAINT users_pkey DO UPDATE ...
EXCLUDED.column
DO UPDATE ... WHERE users.updated_at < EXCLUDED.updated_at
INSERT ... RETURNING id;
UPDATE ... RETURNING *;
DELETE ... RETURNING id, email;
MERGE INTO t USING src ON ... (PG 15+)
Data types
13id BIGINT GENERATED ALWAYS AS IDENTITY
SERIAL / BIGSERIAL
UUID DEFAULT gen_random_uuid()
TEXT
NUMERIC(10, 2)
TIMESTAMPTZ
INTERVAL '2 days 3 hours'
BOOLEAN
JSONB
BYTEA
INET / CIDR / MACADDR
CREATE TYPE status AS ENUM ('new', 'done');
col TEXT GENERATED ALWAYS AS (lower(email)) STORED
Indexes
12CREATE INDEX idx_users_email ON users (email);
CREATE UNIQUE INDEX ... ON users (lower(email));
CREATE INDEX ... ON orders (user_id) WHERE status = 'open';
CREATE INDEX ... USING gin (data);
CREATE INDEX ... USING gin (to_tsvector('english', body));
CREATE INDEX ... USING gist (location);
CREATE INDEX ... USING brin (created_at);
CREATE INDEX CONCURRENTLY ...
CREATE INDEX ... ON t (a, b DESC);
CREATE INDEX ... ON t (a) INCLUDE (b);
REINDEX INDEX CONCURRENTLY idx_name;
DROP INDEX CONCURRENTLY idx_name;
Roles & privileges
11CREATE ROLE app LOGIN PASSWORD 'secret';
CREATE ROLE readonly NOLOGIN;
GRANT readonly TO app;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO readonly;
GRANT USAGE ON SCHEMA public TO app;
REVOKE INSERT ON users FROM app;
ALTER ROLE app SET statement_timeout = '30s';
ALTER TABLE users OWNER TO app;
ALTER TABLE docs ENABLE ROW LEVEL SECURITY;
CREATE POLICY own ON docs USING (owner_id = current_user_id());
Maintenance & EXPLAIN
12EXPLAIN SELECT ...;
EXPLAIN (ANALYZE, BUFFERS) SELECT ...;
VACUUM (VERBOSE) users;
VACUUM FULL users;
ANALYZE users;
SELECT * FROM pg_stat_activity;
SELECT pg_cancel_backend(pid);
SELECT pg_terminate_backend(pid);
SELECT pg_size_pretty(pg_total_relation_size('users'));
SELECT pg_size_pretty(pg_database_size('mydb'));
SELECT * FROM pg_stat_user_indexes;
SELECT * FROM pg_locks WHERE NOT granted;
Backup & restore
12pg_dump mydb > mydb.sql
pg_dump -Fc mydb > mydb.dump
pg_dump -Fd mydb -j 4 -f dumpdir/
pg_dump -t users -t orders mydb
pg_dump --schema-only mydb
pg_dump --data-only mydb
psql mydb < mydb.sql
pg_restore -d mydb -j 4 mydb.dump
pg_restore -l mydb.dump
pg_restore -t users -d mydb mydb.dump
pg_dumpall --globals-only > roles.sql
pg_basebackup -D /backup -Fp -Xs -P
Extensions
11CREATE EXTENSION IF NOT EXISTS pgcrypto;
CREATE EXTENSION "uuid-ossp";
CREATE EXTENSION pg_stat_statements;
CREATE EXTENSION pg_trgm;
CREATE EXTENSION postgis;
CREATE EXTENSION vector;
CREATE EXTENSION hstore;
CREATE EXTENSION postgres_fdw;
CREATE EXTENSION citext;
SELECT * FROM pg_available_extensions;
\dx
“:q”와 일치하는 항목이 없습니다.
PostgreSQL 치트시트 소개
이 PostgreSQL 치트시트는 실제로 자주 입력하는 Postgres 문법을 검색 가능한 한 페이지에 모았습니다: psql 메타 명령어, 쿼리 작성, JSONB, 배열과 range, CTE와 윈도우 함수, upsert와 RETURNING, 데이터 타입, 인덱스, 역할과 권한, 유지보수와 EXPLAIN, 백업과 복원, 그리고 확장 기능까지 다룹니다.
Postgres를 다른 데이터베이스와 다르게 만드는 부분에 초점을 맞춥니다: JSONB 연산자, 배열과 range 타입, RETURNING을 사용한 ON CONFLICT upsert, GIN과 GiST 인덱스, 쿼리가 느릴 때 읽게 되는 EXPLAIN ANALYZE 출력이며, 일상적인 SELECT, JOIN, DDL 문법도 함께 다룹니다.
이 시트는 무료이며 클라이언트 측에서 동작합니다: 검색창으로 실시간으로 행을 필터링하고, 고정된 목차로 섹션을 이동하고, 클릭 한 번으로 문을 복사하고, 책상용 참고자료로 페이지를 인쇄할 수 있습니다.
PostgreSQL 치트시트 사용 방법
- psql 메타 명령어와 쿼리 작성부터 인덱스를 거쳐 확장 기능까지 섹션을 훑어보세요.
- JSONB, ON CONFLICT, EXPLAIN 같은 키워드를 검색해 모든 행을 실시간으로 필터링하세요.
- 문법이 아니라 저장이나 성능에 관한 세부 정보가 필요할 때는 데이터 타입이나 인덱스 섹션으로 이동하세요.
- 문이나 복사 아이콘을 클릭해 SQL을 클립보드에 복사하세요.
- 오프라인 PostgreSQL 참고자료로 시트를 인쇄하세요.