☀️Siang
Database

PostgreSQL untuk Developer: Panduan Lengkap

Tutorial lengkap belajar PostgreSQL dari nol — instalasi, tipe data, queries, joins, indexes, views, stored procedures dengan contoh praktis

Artikel: Postgresql Dasar Artikel: Postgresql Dasar


1. Pengenalan PostgreSQL

PostgreSQL (sering disebut "Postgres") adalah sistem manajemen database relasional (RDBMS) open-source yang powerful dan sangat extensible. Dikembangkan sejak 1986 di University of California, Berkeley, PostgreSQL telah menjadi salah satu database paling populer dan paling dicintai oleh developer di seluruh dunia.

PostgreSQL dikenal karena kepatuhannya terhadap standar SQL, fitur-fitur canggih seperti JSON support, full-text search, dan kemampuan untuk menambahkan tipe data serta fungsi custom. Banyak perusahaan besar seperti Apple, Instagram, Spotify, dan NASA menggunakan PostgreSQL.

Mengapa Memilih PostgreSQL?

Keunggulan Penjelasan
ACID CompliantMenjamin Atomicity, Consistency, Isolation, Durability untuk transaksi yang aman
Standar SQLSangat patuh terhadap standar SQL:2016 — query yang ditulis lebih portabel
JSON & JSONBDukungan native untuk data JSON — bisa digunakan sebagai database NoSQL juga
ExtensibleBisa menambah custom types, operators, functions, bahkan bahasa prosedural
Open SourceLisensi PostgreSQL sangat liberal — bebas digunakan untuk tujuan apapun
Concurrency (MVCC)Multi-Version Concurrency Control memungkinkan banyak user concurrent tanpa locking
Full-Text SearchPencarian teks lengkap built-in tanpa perlu search engine tambahan

PostgreSQL vs Database Lain

Fitur PostgreSQL MySQL SQLite
TipeRDBMS penuhRDBMSEmbedded DB
Standar SQLSangat ketatCukupTerbatas
JSON Support⭐ JSONB kaya fiturPemulaTerbatas
ConcurrencyMVCC tanpa read lockMVCC + table lockSingle writer
Cocok untukAplikasi enterprise, GIS, analyticsWeb app, CMSMobile, embedded
💡 Tips

PostgreSQL tersedia secara gratis di semua platform cloud besar — Amazon RDS, Google Cloud SQL, Azure Database, dan layanan khusus seperti Supabase dan Neon yang menawarkan PostgreSQL serverless dengan free tier.



2. Instalasi & Setup

Instalasi di Berbagai OS

Diagram: Jenis-jenis JOIN
Jenis-jenis JOIN

🐧 Linux

sudo apt install postgresql

sudo systemctl start

sudo -u postgres psql

🍎 macOS

brew install postgresql

brew services start

🪟 Windows

Download installer

Run .exe installer

Add to PATH

✅ psql --version

SQL — Jenis-jenis JOIN
-- INNER JOIN — hanya baris yang cocok di kedua tabel
SELECT m.nama AS mahasiswa, mk.nama_mk, n.nilai, n.grade
FROM nilai n
INNER JOIN mahasiswa m ON n.mahasiswa_id = m.id
INNER JOIN mata_kuliah mk ON n.mata_kuliah_id = mk.id
ORDER BY m.nama, mk.nama_mk;

-- LEFT JOIN — semua baris kiri + yang cocok dari kanan
SELECT m.nama AS mahasiswa, COUNT(n.id) AS jumlah_matkul
FROM mahasiswa m
LEFT JOIN nilai n ON m.id = n.mahasiswa_id
GROUP BY m.nama
ORDER BY jumlah_matkul DESC;

-- RIGHT JOIN — semua baris kanan + yang cocok dari kiri
SELECT mk.nama_mk, COUNT(n.id) AS jumlah_nilai
FROM nilai n
RIGHT JOIN mata_kuliah mk ON n.mata_kuliah_id = mk.id
GROUP BY mk.nama_mk;

-- FULL OUTER JOIN — semua baris dari kedua tabel
SELECT m.nama AS mahasiswa, mk.nama_mk, n.nilai
FROM mahasiswa m
FULL OUTER JOIN nilai n ON m.id = n.mahasiswa_id
FULL OUTER JOIN mata_kuliah mk ON n.mata_kuliah_id = mk.id;

-- SELF JOIN — join tabel dengan dirinya sendiri
-- Contoh: cari mahasiswa dengan IPK sama
SELECT a.nama AS mahasiswa_1, b.nama AS mahasiswa_2, a.ipk
FROM mahasiswa a
INNER JOIN mahasiswa b ON a.ipk = b.ipk AND a.id < b.id;

-- JOIN dengan aggregasi
SELECT
    m.nama,
    ROUND(AVG(n.nilai), 2) AS rata_nilai,
    COUNT(n.id) AS jumlah_mk,
    SUM(mk.sks) AS total_sks
FROM mahasiswa m
JOIN nilai n ON m.id = n.mahasiswa_id
JOIN mata_kuliah mk ON n.mata_kuliah_id = mk.id
GROUP BY m.nama
HAVING AVG(n.nilai) >= 80
ORDER BY rata_nilai DESC;


6. Indexes

Index adalah struktur data yang mempercepat proses pencarian data dalam tabel. Tanpa index, database harus melakukan full table scan — memeriksa setiap baris satu per satu. Dengan index, pencarian bisa dilakukan dalam waktu logaritmik (O(log n)).

Jenis Index di PostgreSQL

Jenis Index Algoritma Cocok Untuk
B-treeBinary tree (default)Equality, range, sorting — paling umum
HashHash tableHanya equality comparison (=)
GINGeneralized Inverted IndexFull-text search, array, JSONB
GiSTGeneralized Search TreeSpatial data (GIS), range types
BRINBlock Range IndexTabel besar dengan data terurut kronologis
SQL — Membuat & Menggunakan Index
-- B-tree index (default) — untuk pencarian umum
CREATE INDEX idx_mahasiswa_nama ON mahasiswa(nama);

-- Composite index — index pada multiple kolom
CREATE INDEX idx_nilai_mhs_mk ON nilai(mahasiswa_id, mata_kuliah_id);

-- Unique index — memastikan nilai unik
CREATE UNIQUE INDEX idx_mahasiswa_nim ON mahasiswa(nim);

-- Partial index — hanya index baris yang memenuhi kondisi
CREATE INDEX idx_mahasiswa_aktif ON mahasiswa(nama)
WHERE aktif = TRUE;

-- GIN index untuk JSONB
CREATE INDEX idx_mahasiswa_alamat ON mahasiswa USING GIN(alamat);

-- GIN index untuk full-text search
CREATE INDEX idx_mahasiswa_nama_search ON mahasiswa
USING GIN(to_tsvector('indonesian', nama));

-- Cek index yang ada pada tabel
\d mahasiswa

-- Analisis query dengan EXPLAIN ANALYZE
EXPLAIN ANALYZE
SELECT * FROM mahasiswa WHERE nama = 'Budi Santoso';
-- Seq Scan on mahasiswa (before index): 0.045 ms
-- Index Scan using idx_mahasiswa_nama (after index): 0.012 ms

-- Hapus index
DROP INDEX idx_mahasiswa_nama;

-- Rebuild index (setelah banyak INSERT/UPDATE/DELETE)
REINDEX INDEX idx_mahasiswa_nama;
💡 Kapan Menggunakan Index?
  • Kolom yang sering digunakan di WHERE, JOIN, atau ORDER BY
  • Kolom dengan high cardinality (banyak nilai unik, seperti email)
  • Jangan terlalu banyak index — setiap INSERT/UPDATE harus memperbarui index juga
  • Gunakan EXPLAIN ANALYZE untuk memverifikasi index digunakan


7. Views

View adalah query tersimpan yang diperlakukan seperti tabel virtual. View tidak menyimpan data sendiri — ia menjalankan query setiap kali diakses. View berguna untuk menyederhanakan query kompleks dan mengontrol akses data.

SQL — Views
-- View: Ringkasan nilai mahasiswa
CREATE VIEW v_ringkasan_nilai AS
SELECT
    m.nim,
    m.nama AS nama_mahasiswa,
    mk.nama_mk,
    mk.sks,
    n.nilai,
    n.grade,
    d.nama AS nama_dosen
FROM nilai n
JOIN mahasiswa m ON n.mahasiswa_id = m.id
JOIN mata_kuliah mk ON n.mata_kuliah_id = mk.id
JOIN dosen d ON mk.dosen_id = d.id
ORDER BY m.nama, mk.nama_mk;

-- Menggunakan view seperti tabel biasa
SELECT * FROM v_ringkasan_nilai;
SELECT nama_mahasiswa, AVG(nilai) FROM v_ringkasan_nilai GROUP BY nama_mahasiswa;

-- View: IPK Mahasiswa
CREATE VIEW v_ipk_mahasiswa AS
SELECT
    m.nim,
    m.nama,
    ROUND(AVG(n.nilai), 2) AS rata_nilai,
    COUNT(n.id) AS jumlah_mk,
    SUM(mk.sks) AS total_sks,
    CASE
        WHEN AVG(n.nilai) >= 85 THEN 'Cum Laude'
        WHEN AVG(n.nilai) >= 75 THEN 'Baik'
        ELSE 'Cukup'
    END AS predikat
FROM mahasiswa m
JOIN nilai n ON m.id = n.mahasiswa_id
JOIN mata_kuliah mk ON n.mata_kuliah_id = mk.id
GROUP BY m.nim, m.nama
ORDER BY rata_nilai DESC;

-- Materialized View — menyimpan hasil query (perlu refresh)
CREATE MATERIALIZED VIEW mv_statistik_nilai AS
SELECT
    mk.nama_mk,
    COUNT(n.id) AS jumlah_nilai,
    ROUND(AVG(n.nilai), 2) AS rata_nilai,
    MAX(n.nilai) AS nilai_max,
    MIN(n.nilai) AS nilai_min
FROM nilai n
JOIN mata_kuliah mk ON n.mata_kuliah_id = mk.id
GROUP BY mk.nama_mk;

-- Refresh materialized view (harus dilakukan manual)
REFRESH MATERIALIZED VIEW mv_statistik_nilai;

-- Update view
CREATE OR REPLACE VIEW v_ringkasan_nilai AS
SELECT
    m.nim,
    m.nama AS nama_mahasiswa,
    m.ipk,
    mk.nama_mk,
    mk.sks,
    n.nilai,
    n.grade
FROM nilai n
JOIN mahasiswa m ON n.mahasiswa_id = m.id
JOIN mata_kuliah mk ON n.mata_kuliah_id = mk.id;

-- Hapus view
DROP VIEW IF EXISTS v_ringkasan_nilai;


8. Stored Procedures & Functions

Stored procedures dan functions memungkinkan Anda menyimpan logika bisnis langsung di database. Ini mempercepat eksekusi karena mengurangi round-trip antara aplikasi dan database.

Functions

SQL — PL/pgSQL Functions
-- Function sederhana: hitung IPK mahasiswa
CREATE OR REPLACE FUNCTION hitung_ipk(p_mahasiswa_id INTEGER)
RETURNS NUMERIC(3,2) AS $$
DECLARE
    v_ipk NUMERIC(3,2);
BEGIN
    SELECT ROUND(AVG(nilai) / 25.0, 2) INTO v_ipk
    FROM nilai
    WHERE mahasiswa_id = p_mahasiswa_id;

    RETURN COALESCE(v_ipk, 0.00);
END;
$$ LANGUAGE plpgsql;

-- Menggunakan function
SELECT nama, hitung_ipk(id) AS ipk FROM mahasiswa;

-- Function: konversi nilai ke grade
CREATE OR REPLACE FUNCTION konversi_grade(p_nilai NUMERIC)
RETURNS VARCHAR(2) AS $$
BEGIN
    RETURN CASE
        WHEN p_nilai >= 90 THEN 'A'
        WHEN p_nilai >= 85 THEN 'A-'
        WHEN p_nilai >= 80 THEN 'B+'
        WHEN p_nilai >= 75 THEN 'B'
        WHEN p_nilai >= 70 THEN 'B-'
        WHEN p_nilai >= 65 THEN 'C+'
        WHEN p_nilai >= 60 THEN 'C'
        WHEN p_nilai >= 50 THEN 'D'
        ELSE 'E'
    END;
END;
$$ LANGUAGE plpgsql;

-- Function: cek apakah mahasiswa bisa lulus
CREATE OR REPLACE FUNCTION cek_kelulusan(p_mahasiswa_id INTEGER)
RETURNS TABLE(nama TEXT, ipk NUMERIC, total_sks INTEGER, lulus BOOLEAN) AS $$
BEGIN
    RETURN QUERY
    SELECT
        m.nama::TEXT,
        hitung_ipk(m.id),
        COALESCE(SUM(mk.sks), 0)::INTEGER,
        (hitung_ipk(m.id) >= 2.00 AND COALESCE(SUM(mk.sks), 0) >= 144)
    FROM mahasiswa m
    LEFT JOIN nilai n ON m.id = n.mahasiswa_id
    LEFT JOIN mata_kuliah mk ON n.mata_kuliah_id = mk.id
    WHERE m.id = p_mahasiswa_id
    GROUP BY m.id, m.nama;
END;
$$ LANGUAGE plpgsql;

-- Menggunakan function
SELECT * FROM cek_kelulusan(1);

Stored Procedures

SQL — Stored Procedures
-- Procedure: proses pemberian nilai
CREATE OR REPLACE PROCEDURE berikan_nilai(
    p_mahasiswa_id INTEGER,
    p_mata_kuliah_id INTEGER,
    p_nilai NUMERIC
)
LANGUAGE plpgsql
AS $$
DECLARE
    v_grade VARCHAR(2);
BEGIN
    -- Konversi nilai ke grade
    v_grade := konversi_grade(p_nilai);

    -- Insert atau update nilai
    INSERT INTO nilai (mahasiswa_id, mata_kuliah_id, nilai, grade)
    VALUES (p_mahasiswa_id, p_mata_kuliah_id, p_nilai, v_grade)
    ON CONFLICT (mahasiswa_id, mata_kuliah_id)
    DO UPDATE SET
        nilai = EXCLUDED.nilai,
        grade = EXCLUDED.grade;

    -- Update IPK mahasiswa
    UPDATE mahasiswa
    SET ipk = hitung_ipk(p_mahasiswa_id),
        updated_at = CURRENT_TIMESTAMP
    WHERE id = p_mahasiswa_id;

    RAISE NOTICE 'Nilai % (grade: %) berhasil diberikan', p_nilai, v_grade;
END;
$$;

-- Menjalankan procedure
CALL berikan_nilai(1, 3, 92.50);

-- Trigger: otomatis update timestamp
CREATE OR REPLACE FUNCTION update_timestamp()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = CURRENT_TIMESTAMP;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

-- Pasang trigger pada tabel mahasiswa
CREATE TRIGGER trigger_update_timestamp
    BEFORE UPDATE ON mahasiswa
    FOR EACH ROW
    EXECUTE FUNCTION update_timestamp();


9. Quiz: Uji Pemahamanmu!

Setelah membaca tutorial di atas, jawablah 5 pertanyaan berikut untuk menguji pemahamanmu tentang PostgreSQL:

Pertanyaan 1: Apa keunggulan utama PostgreSQL dibanding MySQL?

a) Lebih cepat untuk semua query
b) Kepatuhan standar SQL yang ketat, JSONB yang kaya fitur, dan extensibility
c) Tidak memerlukan instalasi
d) Hanya bisa digunakan di Linux

Pertanyaan 2: Tipe data apa yang digunakan untuk auto-increment di PostgreSQL?

a) AUTO_INCREMENT
b) SERIAL / GENERATED ALWAYS AS IDENTITY
c) INCREMENT
d) SEQUENCE

Pertanyaan 3: JOIN apa yang mengembalikan SEMUA baris dari tabel kiri meskipun tidak ada pasangan?

a) INNER JOIN
b) RIGHT JOIN
c) LEFT JOIN
d) CROSS JOIN

Pertanyaan 4: Apa fungsi utama INDEX dalam database?

a) Mengamankan data dari hacker
b) Mempercepat pencarian data dengan menghindari full table scan
c) Menggabungkan dua tabel
d) Menghapus data duplikat

Pertanyaan 5: Apa perbedaan antara VIEW dan MATERIALIZED VIEW?

a) Tidak ada perbedaan
b) VIEW menjalankan query setiap kali diakses, MATERIALIZED VIEW menyimpan hasil dan perlu di-refresh
c) VIEW hanya untuk SELECT, MATERIALIZED VIEW bisa untuk INSERT
d) VIEW lebih cepat dari MATERIALIZED VIEW
🔍 Zoom
100%
🎨 Tema