// Developer Guide

PostgreSQL Developer Guide

คู่มือสำหรับ Developer — ตั้งแต่ PSQL Commands, DDL/DML พื้นฐาน ไปจนถึง PL/pgSQL, Triggers และ Advanced SQL Techniques

// PSQL Commands

คำสั่ง PSQL ที่ใช้บ่อย

-- เชื่อมต่อ PostgreSQL $ psql -h localhost -U postgres -d mydb -- Meta Commands \l -- List databases \c mydb -- Connect to database \dt -- List tables \d users -- Describe table \di -- List indexes \df -- List functions \dv -- List views \du -- List users/roles \timing -- Toggle query timing \e -- Open editor \i file.sql -- Execute SQL file \o file.txt -- Output to file \q -- Quit
-- DDL พื้นฐาน CREATE DATABASE mydb ENCODING 'UTF8' LC_COLLATE 'th_TH.UTF-8'; CREATE TABLE users ( id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, email TEXT NOT NULL UNIQUE, name TEXT NOT NULL, role TEXT DEFAULT 'user', is_active BOOLEAN DEFAULT TRUE, created_at TIMESTAMPTZ DEFAULT NOW() ); -- Alter Table ALTER TABLE users ADD COLUMN avatar TEXT; ALTER TABLE users DROP COLUMN avatar; ALTER TABLE users RENAME TO members;
// DML — Data Manipulation

DML ที่ทรงพลังของ PostgreSQL

-- INSERT with RETURNING INSERT INTO users (email, name) VALUES ('john@example.com', 'John') RETURNING id, created_at; -- UPSERT (INSERT ON CONFLICT) INSERT INTO users (email, name) VALUES ('john@example.com', 'John Doe') ON CONFLICT (email) DO UPDATE SET name = EXCLUDED.name, updated_at = NOW(); -- UPDATE with RETURNING UPDATE users SET is_active = FALSE WHERE last_login < NOW() - INTERVAL '1 year' RETURNING id, email; -- DELETE with RETURNING DELETE FROM logs WHERE created_at < NOW() - INTERVAL '90 days' RETURNING count(*); -- MERGE (PostgreSQL 15+) MERGE INTO inventory AS target USING new_stock AS source ON target.product_id = source.product_id WHEN MATCHED THEN UPDATE SET qty = target.qty + source.qty WHEN NOT MATCHED THEN INSERT (product_id, qty) VALUES (source.product_id, source.qty);
// Advanced SQL

CTEs & Window Functions

Common Table Expressions (WITH)

-- Recursive CTE สำหรับ Tree Structure WITH RECURSIVE dept_tree AS ( SELECT id, name, parent_id, 0 AS level FROM departments WHERE parent_id IS NULL UNION ALL SELECT d.id, d.name, d.parent_id, dt.level + 1 FROM departments d JOIN dept_tree dt ON d.parent_id = dt.id ) SELECT repeat(' ', level) || name AS tree FROM dept_tree;

Window Functions

-- Rank, Running Total, Lead/Lag SELECT name, salary, RANK() OVER (ORDER BY salary DESC) AS rank, SUM(salary) OVER (ORDER BY name) AS running_total, LAG(salary) OVER (ORDER BY name) AS prev_salary, LEAD(salary) OVER (ORDER BY name) AS next_salary FROM employees; -- Percentile SELECT dept_id, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY salary) AS median_salary FROM employees GROUP BY dept_id;
// PL/pgSQL

PL/pgSQL — Stored Procedures & Functions

-- Function สำหรับคำนวณ CREATE OR REPLACE FUNCTION get_user_stats(p_user_id BIGINT) RETURNS TABLE(order_count INT, total_spent NUMERIC, avg_order NUMERIC) LANGUAGE plpgsql AS $$ BEGIN RETURN QUERY SELECT COUNT(*)::INT, COALESCE(SUM(total), 0), COALESCE(AVG(total), 0) FROM orders WHERE user_id = p_user_id AND status = 'completed'; END; $$; -- Trigger Function CREATE OR REPLACE FUNCTION set_updated_at() RETURNS TRIGGER LANGUAGE plpgsql AS $$ BEGIN NEW.updated_at := NOW(); RETURN NEW; END; $$; CREATE TRIGGER trg_updated_at BEFORE UPDATE ON users FOR EACH ROW EXECUTE FUNCTION set_updated_at();
ต้องการเรียนรู้เพิ่มเติม?
ดูคู่มือ DBA และ Performance Tuning สำหรับ PostgreSQL