Desain Skema Database — SQL

Merancang skema database yang baik adalah salah satu skill terpenting seorang developer. Normalisasi — proses mengorganisir data untuk menghindari redundansi…

Skema adalah denah database: ada tabel apa saja, kolomnya apa, dan bagaimana tabel-tabel itu terhubung. Desain skema yang baik menyimpan setiap fakta sekali saja. Mirip kontak di HP: nomor temanmu disimpan sekali di daftar kontak, dan grup WhatsApp cuma menunjuk ke kontak itu. Kalau temanmu ganti nomor, kamu ubah sekali, dan semua grup ikut benar.

🧪 Tebakan cepat: toko punya 3 produk berkategori Elektronik, dan nama kategorinya mau diganti jadi Gadget. Berapa baris yang harus diubah kalau semua data ada di satu tabel, dan berapa kalau kategori punya tabel sendiri? Tebak dulu, jawabannya ada di bagian "Masalah satu tabel untuk semua".

Masalah satu tabel untuk semua

Ini tabel products_flat: setiap produk menyimpan nama kategorinya sendiri.

id name price category
1 Laptop 12000000 Elektronik
2 Mouse 150000 Elektronik
3 Monitor 3500000 Elektronik
4 Pulpen 5000 Alat Tulis

"Elektronik" tertulis tiga kali. Fakta yang sama disimpan berulang seperti ini disebut redundansi data, dan dia bikin tiga masalah yang bisa kamu coba di Lab:

Yang mau dilakukan Di satu tabel
Ganti nama Elektronik jadi Gadget UPDATE harus mengubah 3 baris. Satu terlewat, datanya saling bertentangan.
Hapus produk Pulpen Kategori Alat Tulis ikut lenyap, karena cuma tercatat di baris Pulpen.
Tambah kategori Buku yang belum punya produk Gak bisa: NOT NULL constraint failed: products_flat.name, karena setiap baris harus berupa produk.

Dua tabel: categories dan products

Solusinya: kategori dapat tabel sendiri, dan produk cuma menyimpan nomornya, persis seperti pelanggan dan pesanan di pelajaran Relasi Antar Tabel.

CREATE TABLE categories (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  name TEXT NOT NULL
);

CREATE TABLE products (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  name TEXT NOT NULL,
  price REAL NOT NULL,
  category_id INTEGER,
  FOREIGN KEY (category_id) REFERENCES categories(id)
);

Isinya: categories berisi (1, Elektronik) dan (2, Alat Tulis). Laptop, Mouse dan Monitor punya category_id 1, Pulpen 2. Sekarang ganti nama cukup satu baris:

UPDATE categories SET name = 'Gadget' WHERE id = 1;

1 baris berubah, dan ketiga produk ikut jadi Gadget waktu di-JOIN. Satu tabel: 3 baris, dua tabel: 1 baris. Itu jawaban tebakannya. Menghapus Pulpen juga gak menghapus Alat Tulis, dan Buku bisa masuk ke categories tanpa produk. Memecah tabel supaya setiap fakta tersimpan sekali seperti ini disebut normalisasi.

Langkah mendesain skema

  1. Daftar benda yang disimpan (entitas): pelanggan, produk, kategori, pesanan.
  2. Satu tabel per benda, nama jamak (customers, products), dengan id sebagai primary key.
  3. Tentukan relasinya. One-to-many: foreign key di sisi banyak (category_id di products). Many-to-many: tabel pivot (bagian berikut).
  4. Tandai kolom wajib dengan NOT NULL.
  5. Foreign key diberi nama tabel bentuk tunggal + _id: category_id, customer_id.

Many-to-many: tabel pivot

Di pelajaran JOIN, orders punya kolom product berisi teks, jadi satu pesanan cuma bisa satu barang. Padahal satu pesanan bisa berisi banyak produk, dan satu produk dibeli di banyak pesanan: many-to-many. Foreign key gak bisa ditaruh di salah satu sisi, jadi dibuat tabel perantara, disebut tabel pivot (atau junction table):

CREATE TABLE order_items (
  order_id INTEGER NOT NULL REFERENCES orders(id),
  product_id INTEGER NOT NULL REFERENCES products(id),
  qty INTEGER NOT NULL,
  PRIMARY KEY (order_id, product_id)
);

Satu baris = satu produk di satu pesanan. PRIMARY KEY (order_id, product_id) adalah primary key gabungan: pasangan yang sama gak boleh muncul dua kali.

📌 Bentuk normal: 1NF, 2NF, 3NF

Aturan normalisasi biasanya ditulis bertingkat:

Gak semua yang mirip itu duplikasi. Harga di order_items (harga saat dibeli) adalah fakta lain dari harga di products (harga hari ini), jadi boleh disimpan dua-duanya.

⚠️ Jebakan yang sering ketemu

TL;DR: Desain skema yang baik menyimpan setiap fakta sekali. Nama kategori yang diulang di setiap produk (redundansi) bikin ganti nama harus mengubah banyak baris (3 baris, bukan 1), menghapus produk terakhir menghapus kategorinya, dan kategori baru gak bisa masuk tanpa produk. Normalisasi memecahnya jadi categories dan products yang dihubungkan category_id + FOREIGN KEY, dengan NOT NULL di kolom wajib. Relasi many-to-many butuh tabel pivot dengan dua foreign key. 1NF: satu sel satu nilai, 2NF: bergantung pada seluruh key, 3NF: gak bergantung pada kolom biasa lain.

Yang akan kamu pelajari