Dasar Database Relasional & Bahasa SQL
Data di memori (dibahas di Java Collections Framework) akan hilang begitu server restart. Untuk penyimpanan permanen, backend mengandalkan database relasional (RDBMS) seperti PostgreSQL, MySQL, atau Oracle. Bahasa yang dipakai untuk berbicara dengan database ini adalah SQL (Structured Query Language).
Konsep Dasar: Tabel, Baris, dan Kolom
Database relasional menyimpan data dalam bentuk tabel — sama seperti spreadsheet. Berikut tabel users contoh:
| id | full_name | created_at | |
|---|---|---|---|
| 1 | hendro@mail.com | Hendro Wunga | 2026-06-01 |
| 2 | endos@mail.com | Endos Dev | 2026-06-02 |
| Istilah | Arti di Database | Arti di Spreadsheet |
|---|---|---|
| Tabel | Struktur penyimpanan | Lembar kerja |
| Kolom / Field / Attribute | Jenis data yang disimpan | Kepala kolom (header) |
| Baris / Record / Tuple | Satu entri data lengkap | Satu baris data |
Setiap kolom punya tipe data yang tegas, misalnya BIGSERIAL (angka auto-increment), VARCHAR(255) (teks), DATE (tanggal), atau BOOLEAN. Tipe data inilah yang menjaga data tetap bersih sejak awal.
DDL vs DML: Dua Jenis Perintah SQL
Semua perintah SQL terbagi menjadi dua keluarga besar. Ini sering keluar di wawancara, dan wajib dipahami secara intuitif.
DDL — Data Definition Language (untuk struktur)
Perintah DDL mengubah struktur database: membuat, mengubah, atau menghapus tabel/kolom. Referensi perintah.
CREATE TABLE users (
id BIGSERIAL PRIMARY KEY,
email VARCHAR(255) NOT NULL UNIQUE,
full_name VARCHAR(255) NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
ALTER TABLE users ADD COLUMN phone VARCHAR(20); -- menambah kolom
DROP TABLE users; -- menghapus tabel
DML — Data Manipulation Language (untuk isi data)
Perintah DML bekerja pada isi data di dalam tabel: menambah, membaca, mengubah, dan menghapus baris.
-- INSERT: tambah baris baru
INSERT INTO users (email, full_name) VALUES ('hendro@mail.com', 'Hendro Wunga');
-- SELECT: ambil data
SELECT id, email, full_name FROM users WHERE role = 'ADMIN' ORDER BY created_at DESC;
-- UPDATE: ubah data yang sudah ada
UPDATE users SET full_name = 'Hendro W. Wunga' WHERE id = 1;
-- DELETE: hapus baris
DELETE FROM users WHERE id = 2;
Cara mudah mengingat: DDL membangun rumah (struktur), DML mengisi rumah (isi). DDL jarang dipakai dari kode aplikasi; DML justru dipakai setiap detik.
Aturan Integritas Data (Constraints)
Constraints adalah aturan yang memaksa database menolak data "nakal" — lapisan pengaman terakhir sebelum data tercatat.
Primary Key — Identitas Unik Setiap Baris
Primary Key menjamin setiap baris punya identitas unik dan tidak boleh NULL. Tanpa ini, dua baris bisa membawa identitas sama dan tidak ada cara membedakannya.
CREATE TABLE users (
id BIGSERIAL PRIMARY KEY, -- setiap baris wajib punya id unik
...
);
Mencoba menyisipkan id yang sudah ada akan ditolak database:
ERROR: duplicate key value violates unique constraint "users_pkey"
Foreign Key — Menghubungkan Relasi Antar Tabel
Foreign Key adalah kolom yang merujuk ke Primary Key tabel lain. Inilah jantung relasi antar tabel.
CREATE TABLE orders (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL REFERENCES users(id), -- FK ke tabel users
total NUMERIC(12,2) NOT NULL,
status VARCHAR(20) NOT NULL DEFAULT 'PENDING'
);
Relasi ini adalah One-to-Many: satu user bisa punya banyak orders, tetapi satu order hanya milik satu user.
users (1) ──────< (N) orders
id user_id (FK → users.id)
Foreign Key memastikan integritas referensial: Anda tidak bisa membuat order dengan user_id yang tidak ada di tabel users, dan (biasanya) tidak bisa menghapus user yang masih punya order.
Penggabungan Tabel: JOIN
Saat data terpisah antar tabel, kita butuh JOIN untuk menggabungkannya dalam satu query. Dua yang paling fundamental:
INNER JOIN — hanya baris yang cocok
INNER JOIN mengembalikan hanya baris yang memiliki pasangan di kedua tabel.
SELECT o.id, o.total, u.email
FROM orders o
INNER JOIN users u ON o.user_id = u.id;
| o.id | o.total | u.email |
|---|---|---|
| 1 | 150000 | hendro@mail.com |
| 2 | 75000 | hendro@mail.com |
LEFT JOIN — semua baris kiri, sisanya NULL
LEFT JOIN mengembalikan semua baris dari tabel kiri, dan mengisi NULL untuk kolom tabel kanan yang tidak punya pasangan.
SELECT u.email, o.total
FROM users u
LEFT JOIN orders o ON o.user_id = u.id;
| u.email | o.total |
|---|---|
| hendro@mail.com | 150000 |
| hendro@mail.com | 75000 |
| endos@mail.com | NULL |
Intuisi cepat:
INNER JOIN= "data yang punya hubungan",LEFT JOIN= "semua data kiri, kalaupun tidak punya hubungan tetap tampil dengan NULL". Left join cocok untuk laporan yang harus menampilkan semua entitas (misal semua user, termasuk yang belum pernah order).
Contoh alur lengkap ala service backend
Bayangkan logika "daftar order dengan email pemiliknya" — di Java dengan Spring Data JPA / JDBC, query SQL yang dikirim ke database persis seperti di atas:
// Query yang dikirim JDBC/JPA ke PostgreSQL
SELECT o.id, o.total, o.status, u.email
FROM orders o
JOIN users u ON o.user_id = u.id
WHERE u.email = ?
ORDER BY o.created_at DESC
LIMIT 20;
Ringkasan
Database relasional menyimpan data dalam tabel (baris + kolom) dengan tipe data yang tegas. DDL membangun struktur, DML mengisi data. Primary Key memberi identitas unik, Foreign Key menghubungkan tabel dan menjaga integritas relasi. Dan JOIN menyatukan data dari tabel-tabel berelasi — INNER JOIN untuk yang punya pasangan, LEFT JOIN untuk mempertahankan semua data sisi kiri.
Lanjut ke Version Control dengan Git untuk mengelola perubahan kode secara kolaboratif.