Sejauh ini kita selalu bekerja dengan tabel yang sudah jadi: kolomnya sudah tersedia, tugas kita tinggal mengisi dan mengkuerinya. Ketika aplikasi baru akan dibangun, tabel-tabel itu belum ada — kita yang harus memutuskan tabel apa saja yang dibuat, kolom apa saja yang dimilikinya, dan tipe data apa yang paling tepat untuk tiap kolom. Keputusan-keputusan tersebut adalah inti section relational database design, dan langkah pertamanya bukan menulis CREATE TABLE, melainkan memodelkan kebutuhan menjadi entitas dan atribut. Chapter ini membahas cara membaca deskripsi kebutuhan, mengenali entitas di dalamnya, menurunkan entitas menjadi tabel, dan menurunkan atribut menjadi kolom. Sepanjang praktik kita memakai satu studi kasus yang sama: toko kecil bernama Toko Maju Jaya.

Entitas: Hal yang Datanya Kita Simpan #

Entitas adalah “hal yang kita simpan datanya” — orang, benda, kejadian, atau konsep yang aplikasi perlukan untuk diingat. Pada aplikasi toko, entitas yang paling tampak adalah pelanggan, produk, dan pesanan: ketiganya adalah sesuatu yang jumlah datanya terus bertambah dan perlu dilacak. Setiap entitas kelak menjadi satu tabel, dan setiap baris tabel mewakili satu kejadian nyata dari entitas tersebut — satu orang pelanggan tertentu, satu produk tertentu, satu transaksi tertentu. Tabel berikut memetakan ketiganya:

EntitasContoh satu baris dataPertanyaan yang dijawab
pelangganBudi Santoso dari Jakartasiapa yang berbelanja di toko
produkObeng Set 6pcs seharga 35000apa saja yang dijual toko
pesanantransaksi tanggal 2026-01-12 senilai 15000kapan siapa membeli apa

Pemisahan entitas berarti pemisahan tabel, dan pemisahan inilah yang membuat data bisa dikelola tanpa saling menimpa. Nama pelanggan cukup disimpan sekali di tabel pelanggan; data transaksi di tabel lain cukup menyimpan penunjuk ke baris pelanggan yang dimaksud. Bagaimana kedua tabel saling menunjuk akan menjadi tema chapter-chapter relasi setelah ini — sekarang kita fokus menemukan entitas dan atributnya terlebih dahulu.

Atribut Menjadi Kolom #

Atribut adalah ciri yang kita rekam tentang sebuah entitas. Pelanggan memiliki nama, telepon, dan kota; produk memiliki nama, harga, dan stok; pesanan memiliki tanggal dan total. Ketika entitas menjadi tabel, setiap atribut menjadi satu kolom, dan nilai atribut pada satu kejadian menjadi isi sel pada baris tersebut. Pemilihan atribut adalah keputusan desain: kita hanya merekam ciri yang benar-benar dibutuhkan aplikasi, bukan semua ciri yang mungkin ada di dunia nyata. Toko Maju Jaya mungkin peduli warna kemasan produk, tetapi selama aplikasi tidak pernah menampilkan informasi itu, atribut tersebut tidak perlu menjadi kolom.

Dari Paragraf Kebutuhan ke Daftar Entitas #

Entitas tidak muncul dari kebiasaan menulis SQL, melainkan dari deskripsi masalah yang diberikan pengguna. Teknik paling sederhana untuk menemukannya adalah membaca deskripsi kebutuhan sambil menandai kata benda penting, lalu mengklasifikasikan setiap kata benda: apakah layak menjadi entitas, menjadi atribut milik entitas lain, atau hanyalah konteks yang tidak perlu disimpan. Berikut deskripsi kebutuhan Toko Maju Jaya versi pemiliknya:

“Toko Maju Jaya menjual perkakas dan elektronik. Setiap produk punya nama, harga, dan jumlah stok. Pelanggan terdaftar menyimpan nama, telepon, dan kota asalnya. Setiap kali pelanggan membeli, kasir mencatat satu pesanan berisi tanggal dan total, dan satu pesanan berisi beberapa produk dengan jumlah masing-masing.”

Kita tandai setiap kata benda lalu klasifikasikan pada tabel berikut:

Kata bendaKeputusanAlasan
Toko Maju Jayakonteks, bukan entitashanya satu toko; tidak ada data yang perlu dilacak
produkentitasjumlahnya banyak dan terus bertambah
nama, harga, stokatribut produkciri milik setiap produk
pelangganentitasdatanya perlu disimpan dan dicari kembali
nama, telepon, kotaatribut pelangganciri milik setiap pelanggan
pesananentitaskejadian transaksi yang perlu direkam
tanggal, totalatribut pesananciri milik setiap transaksi
jumlah masing-masingatribut milik pasangan pesanan-produknilainya berbeda per kombinasi, bukan milik satu entitas — teaser untuk chapter junction table

Perhatikan baris terakhir: jumlah pembelian bukan atribut pesanan saja, bukan pula atribut produk saja, melainkan atribut milik kombinasi keduanya. Fakta kecil ini kelak menentukan bentuk tabel perantara di chapter RELASI MANY TO MANY. Kata benda “kasir” sengaja tidak dimasukkan pada studi kasus ini agar contoh tetap ramping; pada aplikasi yang lebih besar, kasir bisa saja menjadi entitas pegawai tersendiri.

Memilih Tipe Data untuk Setiap Atribut #

Setelah daftar entitas dan atribut tersusun, kita memilih tipe data tiap kolom. Prinsipnya: tipe harus mewakili sifat nilainya — angka yang dihitung memakai tipe numerik, uang memakai DECIMAL agar presisi desimalnya terjaga, tanggal memakai DATE, dan teks pendek memakai VARCHAR dengan panjang yang wajar. Nomor telepon sengaja kita simpan sebagai VARCHAR, bukan INT, karena nomor telepon berawalan nol, bisa memuat tanda hubung, dan tidak pernah dihitung secara aritmetika.

EntitasAtributTipe dataAlasan
produknamaVARCHAR(50)teks pendek dengan panjang bervariasi
produkhargaDECIMAL(10,2)nilai uang butuh dua desimal eksak
produkstokINTbilangan bulat yang bisa ditambah/kurang
pelanggannamaVARCHAR(50)teks pendek
pelangganteleponVARCHAR(15)teks: berawalan 0 dan tak dihitung
pelanggankotaVARCHAR(30)teks pendek
pesanantanggalDATEnilai tanggal tanpa jam
pesanantotalDECIMAL(12,2)nilai uang, presisi 2 desimal

Entitas Kuat dan Entitas Lemah #

Belum semua entitas setara. Entitas kuat adalah entitas yang bisa diidentifikasi berdiri sendiri: produk bisa diberi nomor id sendiri dan langsung dikenali. Entitas lemah adalah entitas yang keberadaannya bergantung pada entitas lain — contohnya baris rincian pesanan: “2 buah Obeng Set pada pesanan nomor 12”. Rincian seperti ini tidak punya arti tanpa pesanan induknya; ia bahkan sulit diberi nomor urut yang bermakna di luar pesanan tersebut. Pada model relasional, entitas lemah diterjemahkan menjadi tabel anak yang primary key-nya memuat kolom penunjuk ke induknya — pola yang akan kita implementasikan penuh saat membahas relasi satu-ke-banyak dan junction table.

Praktik: Dari Deskripsi Toko ke Tabel #

Saatnya mewujudkan hasil analisis menjadi tabel sungguhan. Kita mulai dari dua entitas kuat yang berdiri sendiri — produk dan pelanggan — karena keduanya belum saling bergantung; entitas pesanan sengaja ditunda sampai kita mengenal relasi antartabel. Database latihan section ini bernama belajar_rdb:

sql
DROP DATABASE IF EXISTS belajar_rdb;
CREATE DATABASE belajar_rdb;
USE belajar_rdb;

CREATE TABLE produk (
  id INT AUTO_INCREMENT PRIMARY KEY,
  nama VARCHAR(50) NOT NULL,
  harga DECIMAL(10,2) NOT NULL,
  stok INT NOT NULL DEFAULT 0
);

CREATE TABLE pelanggan (
  id INT AUTO_INCREMENT PRIMARY KEY,
  nama VARCHAR(50) NOT NULL,
  telepon VARCHAR(15) NOT NULL,
  kota VARCHAR(30) NOT NULL
);

Output yang Dihasilkan:

text
Query OK, 0 rows affected, 1 warning (0.00 sec)

Query OK, 1 row affected (0.00 sec)

Database changed
Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

Mari kita bedah struktur di atas baris per baris:

  1. DROP DATABASE IF EXISTS sampai USE — tiga baris pembuka memastikan setiap pembaca memulai dari kondisi sama: database lama bernama sama dibuang bila ada, database baru dibuat, lalu sesi aktif berpindah ke database tersebut.
  2. id INT AUTO_INCREMENT PRIMARY KEY — setiap tabel diberi primary key buatan berupa bilangan bulat yang bertambah otomatis; nomor ini menjadi identitas resmi baris.
  3. nama VARCHAR(50) NOT NULL — nama wajib terisi untuk setiap produk dan pelanggan; string kosong diperbolehkan secara tipe, tetapi NULL ditolak.
  4. harga DECIMAL(10,2) — tipe uang dengan total 10 digit dan 2 desimal, cukup untuk harga hingga ratusan juta rupiah.
  5. stok INT NOT NULL DEFAULT 0 — produk baru boleh ditambahkan dulu tanpa mengisi stok; nilainya otomatis 0 hingga diubah.

Sekarang kita isi data contoh dari hasil analisis atribut:

sql
INSERT INTO produk (nama, harga, stok) VALUES
  ('Obeng Set 6pcs', 35000.00, 40),
  ('Bor Listrik 500W', 485000.00, 12),
  ('Gergaji Tangan', 95000.00, 25),
  ('Tang Kombinasi 8in', 48000.00, 30),
  ('Ampul LED 12W', 25000.00, 100);

INSERT INTO pelanggan (nama, telepon, kota) VALUES
  ('Budi Santoso', '021-5550111', 'Jakarta'),
  ('Siti Rahayu', '022-5550122', 'Bandung'),
  ('Andi Wijaya', '031-5550133', 'Surabaya'),
  ('Rina Melati', '0274-5550144', 'Yogyakarta');

Output yang Dihasilkan:

text
Query OK, 5 rows affected (0.00 sec)
Records: 5  Duplicates: 0  Warnings: 0

Query OK, 4 rows affected (0.00 sec)
Records: 4  Duplicates: 0  Warnings: 0
sql
SELECT * FROM produk ORDER BY id;

Output yang Dihasilkan:

text
+----+--------------------+-----------+------+
| id | nama               | harga     | stok |
+----+--------------------+-----------+------+
|  1 | Obeng Set 6pcs     |  35000.00 |   40 |
|  2 | Bor Listrik 500W   | 485000.00 |   12 |
|  3 | Gergaji Tangan     |  95000.00 |   25 |
|  4 | Tang Kombinasi 8in |  48000.00 |   30 |
|  5 | Ampul LED 12W      |  25000.00 |  100 |
+----+--------------------+-----------+------+
5 rows in set (0.00 sec)
sql
SELECT * FROM pelanggan ORDER BY id;

Output yang Dihasilkan:

text
+----+--------------+--------------+------------+
| id | nama         | telepon      | kota       |
+----+--------------+--------------+------------+
|  1 | Budi Santoso | 021-5550111  | Jakarta    |
|  2 | Siti Rahayu  | 022-5550122  | Bandung    |
|  3 | Andi Wijaya  | 031-5550133  | Surabaya   |
|  4 | Rina Melati  | 0274-5550144 | Yogyakarta |
+----+--------------+--------------+------------+
4 rows in set (0.00 sec)

Setiap baris hasil kini tepat mewakili satu kejadian entitas: lima produk dan empat pelanggan, masing-masing dengan identitas id sendiri. Diagram entity-relationship berikut merangkum dua entitas yang sudah kita bangun — atributnya tertulis di dalam kotak, sedangkan garis relasi antarentitas belum ada karena memang belum kita buat:

Membersihkan Database Latihan #

sql
DROP DATABASE belajar_rdb;

Output yang Dihasilkan:

text
Query OK, 2 rows affected (0.00 sec)

Referensi #

Kita sudah bisa berpindah dari paragraf kebutuhan menjadi tabel: kata benda penting menjadi entitas, ciri miliknya menjadi atribut dan kolom, serta tipe data dipilih mengikuti sifat nilainya. Namun dua tabel yang kita buat masih berdiri sendiri-sendiri — aplikasi nyata justru hidup dari hubungan antardata, seperti pesanan yang menunjuk pelanggan dan produk tertentu. Chapter berikutnya memulai dari bentuk hubungan paling sederhana: relasi satu-ke-satu dan alasan memecah satu tabel menjadi dua.