3040 kata
15 menit

Studi Kasus MySQL: Membuat Database Toko Online Sederhana

Akhirnya kita sampai di Bab 8, sekaligus bab terakhir dari Series Belajar Database MySQL dari Nol.

Selama tujuh bab sebelumnya, kita sudah mempelajari berbagai konsep dasar dan lanjutan MySQL.

Mulai dari mengenal database, memasang MySQL dan DBeaver, membuat tabel, menjalankan CRUD, menghubungkan tabel menggunakan foreign key dan JOIN, membuat laporan dengan GROUP BY, hingga mengenal index dan transaction.

Sekarang waktunya menggabungkan semuanya menjadi sebuah proyek kecil.

Kita akan membuat database toko online sederhana yang bisa menyimpan produk, pelanggan, pesanan, dan detail pembelian.

Di akhir tutorial, kita akan mempunyai database yang dapat digunakan untuk mencatat transaksi dan menghasilkan laporan penjualan.

Tentu saja, ini belum menjadi aplikasi e-commerce lengkap seperti marketplace besar.

Belum ada keranjang belanja, pembayaran otomatis, pengiriman, ataupun integrasi backend.

Namun, fondasi database yang kita buat sudah cukup untuk memahami bagaimana data transaksi saling terhubung.

Dan yang paling penting, seluruh praktik dapat dikerjakan langsung menggunakan MySQL dan DBeaver.

Apa yang Akan Kita Bangun?#

Kita akan membuat empat tabel utama.

TabelFungsi
pelangganMenyimpan informasi pelanggan
produkMenyimpan daftar produk, harga, dan stok
pesananMenyimpan informasi pesanan
detail_pesananMenyimpan daftar produk yang dibeli dalam setiap pesanan

Hubungan antartabelnya:

pelanggan
|
| 1 : N
|
pesanan
|
| 1 : N
|
detail_pesanan
|
| N : 1
|
produk

Satu pelanggan dapat membuat banyak pesanan.

Satu pesanan dapat mempunyai banyak detail pembelian.

Satu produk dapat muncul dalam banyak detail pesanan.

Dengan struktur seperti ini, kita tidak perlu menyalin seluruh informasi pelanggan dan produk ke setiap baris transaksi.

Persiapan Sebelum Praktik#

Pastikan kamu sudah mempunyai:

  • MySQL Server yang berjalan.
  • DBeaver yang terhubung ke MySQL.
  • Akses untuk membuat database dan tabel.
  • Pemahaman dasar tentang SQL.

Jika belum pernah memasang MySQL atau menggunakan DBeaver, kamu bisa membaca Bab 2 terlebih dahulu.

Penting: Pada bab ini kita menggunakan database baru bernama db_toko_bapakgabut_final.

Kita sengaja tidak menggunakan db_toko_bapakgabut dari bab sebelumnya.

Tujuannya agar pembaca bisa mengikuti studi kasus dari database kosong tanpa mengganggu data latihan yang sudah dibuat.

Langkah 1 — Membuat Database Baru#

Buka SQL Editor pada DBeaver.

Kemudian jalankan:

CREATE DATABASE IF NOT EXISTS db_toko_bapakgabut_final;

Setelah database dibuat, pilih database tersebut:

USE db_toko_bapakgabut_final;

Untuk memastikan database aktif:

SELECT DATABASE() AS database_aktif;

Hasil yang diharapkan:

db_toko_bapakgabut_final

Perintah CREATE DATABASE IF NOT EXISTS tidak menghapus database yang sudah ada.

Namun, jika database dengan nama tersebut sudah berisi tabel atau data dari latihan sebelumnya, isi tersebut tetap ada.

Agar hasil tutorial mudah diikuti, sebaiknya gunakan database yang benar-benar kosong.

Jangan menjalankan perintah penghapusan database jika masih ada data penting di dalamnya.

Langkah 2 — Membuat Tabel Pelanggan#

Kita mulai dari tabel pelanggan.

CREATE TABLE pelanggan (
id_pelanggan INT AUTO_INCREMENT PRIMARY KEY,
nama_pelanggan VARCHAR(100) NOT NULL,
email VARCHAR(150) NOT NULL UNIQUE,
tanggal_daftar DATE NOT NULL
) ENGINE=InnoDB;

Penjelasan:

  • id_pelanggan merupakan primary key.
  • AUTO_INCREMENT membuat ID bertambah otomatis.
  • nama_pelanggan menyimpan nama pelanggan.
  • email menyimpan alamat email.
  • UNIQUE mencegah dua pelanggan menggunakan email yang sama.
  • tanggal_daftar menyimpan tanggal pendaftaran.

Pada studi kasus ini, kita menggunakan UNIQUE untuk email agar satu alamat email hanya digunakan oleh satu pelanggan.

Aturan tersebut merupakan keputusan desain untuk contoh aplikasi kita.

Langkah 3 — Membuat Tabel Produk#

Sekarang kita membuat tabel produk.

CREATE TABLE produk (
id_produk INT AUTO_INCREMENT PRIMARY KEY,
nama_produk VARCHAR(100) NOT NULL,
harga DECIMAL(12,2) NOT NULL,
stok INT NOT NULL DEFAULT 0,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
INDEX idx_produk_nama (nama_produk)
) ENGINE=InnoDB;

Kita menggunakan DECIMAL(12,2) untuk menyimpan harga agar perhitungan nominal tidak bergantung pada representasi floating point biner.

Kolom stok menggunakan nilai default nol.

Kita juga langsung membuat index pada nama_produk.

Index ini dapat membantu pencarian berdasarkan nama produk ketika jumlah data semakin besar dan kondisi query sesuai.

Pada tabel kecil, MySQL mungkin tetap memilih full table scan.

Langkah 4 — Membuat Tabel Pesanan#

Tabel pesanan menyimpan informasi utama transaksi.

CREATE TABLE pesanan (
id_pesanan INT AUTO_INCREMENT PRIMARY KEY,
id_pelanggan INT NOT NULL,
tanggal_pesanan DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
status_pesanan VARCHAR(20) NOT NULL DEFAULT 'baru',
CONSTRAINT fk_pesanan_pelanggan
FOREIGN KEY (id_pelanggan)
REFERENCES pelanggan(id_pelanggan)
ON UPDATE RESTRICT
ON DELETE RESTRICT,
INDEX idx_pesanan_pelanggan_tanggal (
id_pelanggan,
tanggal_pesanan
)
) ENGINE=InnoDB;

Kolom id_pelanggan merupakan foreign key yang mengacu pada tabel pelanggan.

Artinya, setiap pesanan harus mempunyai pelanggan yang valid.

Kita menggunakan ON DELETE RESTRICT agar pelanggan yang masih mempunyai pesanan tidak dapat dihapus begitu saja.

Composite index pada id_pelanggan dan tanggal_pesanan disiapkan untuk mendukung pola pencarian riwayat pesanan berdasarkan pelanggan dan tanggal.

Langkah 5 — Membuat Tabel Detail Pesanan#

Sekarang kita membuat tabel penghubung antara pesanan dan produk.

CREATE TABLE detail_pesanan (
id_detail INT AUTO_INCREMENT PRIMARY KEY,
id_pesanan INT NOT NULL,
id_produk INT NOT NULL,
jumlah INT NOT NULL,
harga_satuan DECIMAL(12,2) NOT NULL,
CONSTRAINT fk_detail_pesanan
FOREIGN KEY (id_pesanan)
REFERENCES pesanan(id_pesanan)
ON UPDATE RESTRICT
ON DELETE RESTRICT,
CONSTRAINT fk_detail_produk
FOREIGN KEY (id_produk)
REFERENCES produk(id_produk)
ON UPDATE RESTRICT
ON DELETE RESTRICT
) ENGINE=InnoDB;

Tabel tersebut mempunyai dua foreign key:

  • id_pesanan mengacu pada tabel pesanan.
  • id_produk mengacu pada tabel produk.

Kita menyimpan harga_satuan pada detail transaksi karena harga produk dapat berubah di kemudian hari.

Misalnya, sebuah mouse dibeli seharga Rp135.000.

Jika harga produk naik menjadi Rp150.000 minggu depan, nilai transaksi lama harus tetap menggunakan harga saat pembelian.

Langkah 6 — Memeriksa Struktur Database#

Sekarang jalankan:

SHOW TABLES;

Hasil yang diharapkan:

pelanggan
produk
pesanan
detail_pesanan

Urutan tampilannya bisa berbeda.

Untuk memeriksa struktur tabel:

DESCRIBE pelanggan;
DESCRIBE produk;
DESCRIBE pesanan;
DESCRIBE detail_pesanan;

Untuk melihat foreign key dan index secara lebih lengkap, gunakan:

SHOW CREATE TABLE pesanan;
SHOW CREATE TABLE detail_pesanan;

Sampai di sini, kita sudah menyelesaikan struktur dasar database toko online.

Langkah 7 — Mengisi Data Pelanggan#

Sekarang kita tambahkan empat pelanggan.

INSERT INTO pelanggan (
nama_pelanggan,
email,
tanggal_daftar
)
VALUES
('Andi', 'andi@example.com', '2026-10-01'),
('Budi', 'budi@example.com', '2026-10-02'),
('Citra', 'citra@example.com', '2026-10-03'),
('Dina', 'dina@example.com', '2026-10-04');

Periksa hasilnya:

SELECT *
FROM pelanggan
ORDER BY id_pelanggan;

Karena email menggunakan UNIQUE, menjalankan INSERT yang sama untuk kedua kalinya akan menghasilkan error duplicate key.

Hal tersebut merupakan perilaku yang diharapkan.

Langkah 8 — Mengisi Data Produk#

Tambahkan lima produk.

INSERT INTO produk (
nama_produk,
harga,
stok
)
VALUES
('Keyboard Mechanical', 325000, 20),
('Mouse Wireless', 135000, 25),
('Monitor 24 Inch', 1650000, 8),
('USB Flashdisk 64GB', 85000, 40),
('Headset Gaming', 275000, 12);

Periksa:

SELECT
id_produk,
nama_produk,
harga,
stok
FROM produk
ORDER BY id_produk;

Sekarang toko kita sudah mempunyai pelanggan dan produk.

Tetapi belum ada transaksi.

Kita akan menambahkan transaksi menggunakan transaction agar pembuatan pesanan, detail pembelian, dan pengurangan stok dilakukan sebagai satu kesatuan.

Langkah 9 — Membuat Transaksi Pembelian Pertama#

Skenarionya:

Andi membeli satu Keyboard Mechanical dan dua Mouse Wireless.

Totalnya:

Keyboard Mechanical
1 × 325000 = 325000
Mouse Wireless
2 × 135000 = 270000
Total = 595000

Kita akan menggunakan transaction.

Penting: Jalankan langkah-langkah berikut secara berurutan pada satu sesi koneksi MySQL yang sama.

Jangan langsung menjalankan COMMIT jika salah satu perintah gagal.

9.1 Menentukan ID Pelanggan dan Produk#

Pertama, cari ID berdasarkan email dan nama produk.

SELECT id_pelanggan, nama_pelanggan
FROM pelanggan
WHERE email = 'andi@example.com';
SELECT id_produk, nama_produk, harga, stok
FROM produk
WHERE nama_produk IN (
'Keyboard Mechanical',
'Mouse Wireless'
);

Jika data dimasukkan pada database kosong sesuai urutan tutorial, biasanya ID Andi adalah 1, Keyboard Mechanical adalah 1, dan Mouse Wireless adalah 2.

Namun, kita tidak akan bergantung pada asumsi tersebut.

Gunakan variabel sesi:

SET @id_andi = (
SELECT id_pelanggan
FROM pelanggan
WHERE email = 'andi@example.com'
);
SET @id_keyboard = (
SELECT id_produk
FROM produk
WHERE nama_produk = 'Keyboard Mechanical'
LIMIT 1
);
SET @id_mouse = (
SELECT id_produk
FROM produk
WHERE nama_produk = 'Mouse Wireless'
LIMIT 1
);

Pastikan semua variabel mempunyai nilai:

SELECT
@id_andi AS id_andi,
@id_keyboard AS id_keyboard,
@id_mouse AS id_mouse;

Jika salah satu bernilai NULL, jangan melanjutkan transaksi.

9.2 Memulai Transaction#

Jalankan:

START TRANSACTION;

Kunci baris produk yang akan dibeli:

SELECT
id_produk,
nama_produk,
harga,
stok
FROM produk
WHERE id_produk IN (@id_keyboard, @id_mouse)
ORDER BY id_produk
FOR UPDATE;

Periksa bahwa:

  • Stok Keyboard Mechanical minimal 1.
  • Stok Mouse Wireless minimal 2.

Jika stok tidak mencukupi, jalankan:

ROLLBACK;

Dan hentikan proses pembelian.

9.3 Membuat Pesanan#

Jika stok mencukupi, buat pesanan:

INSERT INTO pesanan (
id_pelanggan,
status_pesanan
)
VALUES (
@id_andi,
'baru'
);

Ambil ID pesanan:

SET @id_pesanan_andi = LAST_INSERT_ID();

9.4 Membuat Detail Pesanan#

Tambahkan dua produk ke detail pesanan:

INSERT INTO detail_pesanan (
id_pesanan,
id_produk,
jumlah,
harga_satuan
)
VALUES
(@id_pesanan_andi, @id_keyboard, 1, 325000),
(@id_pesanan_andi, @id_mouse, 2, 135000);

Nilai harga satuan pada contoh ini merupakan harga transaksi yang sudah kita tetapkan.

Dalam aplikasi nyata, backend harus memastikan harga yang digunakan sesuai dengan aturan bisnis dan sumber harga tepercaya.

9.5 Mengurangi Stok#

Sekarang kurangi stok keyboard:

UPDATE produk
SET stok = stok - 1
WHERE id_produk = @id_keyboard
AND stok >= 1;

Segera setelah UPDATE tersebut, periksa jumlah baris yang berubah:

SELECT ROW_COUNT() AS keyboard_diubah;

Hasil yang diharapkan adalah 1.

Jika hasilnya bukan 1, jalankan ROLLBACK dan jangan lanjutkan.

Kemudian kurangi stok mouse:

UPDATE produk
SET stok = stok - 2
WHERE id_produk = @id_mouse
AND stok >= 2;

Segera periksa:

SELECT ROW_COUNT() AS mouse_diubah;

Hasil yang diharapkan juga 1.

Jika hasilnya bukan 1, jalankan ROLLBACK.

9.6 Menyimpan Transaksi#

Jika semua langkah berhasil, jalankan:

COMMIT;

Sekarang pesanan Andi, detail pembelian, dan pengurangan stok sudah disimpan bersama.

Jika ada error sebelum COMMIT, jalankan ROLLBACK pada sesi yang sama.

Catatan: Transaction ini merupakan latihan manual. Pada aplikasi produksi, seluruh proses biasanya diatur oleh backend yang menangani error, retry, validasi harga, dan status transaksi secara terprogram.

Langkah 10 — Membuat Transaksi Pembelian Kedua#

Sekarang Budi membeli satu Monitor 24 Inch.

Harga transaksinya Rp1.650.000.

Pertama, ambil ID:

SET @id_budi = (
SELECT id_pelanggan
FROM pelanggan
WHERE email = 'budi@example.com'
);
SET @id_monitor = (
SELECT id_produk
FROM produk
WHERE nama_produk = 'Monitor 24 Inch'
LIMIT 1
);

Periksa:

SELECT
@id_budi AS id_budi,
@id_monitor AS id_monitor;

Jika ID tersedia, mulai transaksi:

START TRANSACTION;

Kunci baris monitor:

SELECT
id_produk,
nama_produk,
stok
FROM produk
WHERE id_produk = @id_monitor
FOR UPDATE;

Pastikan stok minimal satu.

Jika tidak mencukupi, jalankan ROLLBACK dan hentikan proses.

Buat pesanan:

INSERT INTO pesanan (
id_pelanggan,
status_pesanan
)
VALUES (
@id_budi,
'baru'
);

Ambil ID pesanan:

SET @id_pesanan_budi = LAST_INSERT_ID();

Tambahkan detail:

INSERT INTO detail_pesanan (
id_pesanan,
id_produk,
jumlah,
harga_satuan
)
VALUES (
@id_pesanan_budi,
@id_monitor,
1,
1650000
);

Kurangi stok:

UPDATE produk
SET stok = stok - 1
WHERE id_produk = @id_monitor
AND stok >= 1;

Segera periksa:

SELECT ROW_COUNT() AS monitor_diubah;

Jika hasilnya 1 dan seluruh langkah sebelumnya berhasil:

COMMIT;

Jika gagal:

ROLLBACK;

Sampai di sini, kita mempunyai dua pesanan contoh.

Langkah 11 — Menampilkan Riwayat Transaksi dengan JOIN#

Sekarang kita ingin menampilkan laporan transaksi.

Gunakan query:

SELECT
p.id_pesanan,
pl.nama_pelanggan,
pr.nama_produk,
dp.jumlah,
dp.harga_satuan,
dp.jumlah * dp.harga_satuan AS subtotal
FROM pesanan p
INNER JOIN pelanggan pl
ON p.id_pelanggan = pl.id_pelanggan
INNER JOIN detail_pesanan dp
ON p.id_pesanan = dp.id_pesanan
INNER JOIN produk pr
ON dp.id_produk = pr.id_produk
ORDER BY p.id_pesanan, dp.id_detail;

Jika mengikuti seluruh langkah dengan database kosong, hasilnya kurang lebih:

PelangganProdukJumlahSubtotal
AndiKeyboard Mechanical1325000
AndiMouse Wireless2270000
BudiMonitor 24 Inch11650000

ID pesanan mengikuti nilai AUTO_INCREMENT pada database masing-masing.

Langkah 12 — Membuat Laporan Total Pembelian#

Kita ingin mengetahui total nilai pembelian setiap pelanggan.

SELECT
pl.id_pelanggan,
pl.nama_pelanggan,
SUM(dp.jumlah * dp.harga_satuan) AS total_pembelian
FROM pelanggan pl
INNER JOIN pesanan p
ON pl.id_pelanggan = p.id_pelanggan
INNER JOIN detail_pesanan dp
ON p.id_pesanan = dp.id_pesanan
GROUP BY
pl.id_pelanggan,
pl.nama_pelanggan
ORDER BY total_pembelian DESC;

Hasil yang diharapkan:

PelangganTotal Pembelian
Budi1650000
Andi595000

Citra dan Dina tidak muncul karena belum mempunyai transaksi.

Jika ingin menampilkan seluruh pelanggan, kita bisa menggunakan LEFT JOIN.

SELECT
pl.id_pelanggan,
pl.nama_pelanggan,
COUNT(DISTINCT p.id_pesanan) AS jumlah_pesanan,
COALESCE(
SUM(dp.jumlah * dp.harga_satuan),
0
) AS total_pembelian
FROM pelanggan pl
LEFT JOIN pesanan p
ON pl.id_pelanggan = p.id_pelanggan
LEFT JOIN detail_pesanan dp
ON p.id_pesanan = dp.id_pesanan
GROUP BY
pl.id_pelanggan,
pl.nama_pelanggan
ORDER BY total_pembelian DESC;

Sekarang Citra dan Dina tetap muncul dengan total pembelian nol.

Langkah 13 — Membuat Laporan Produk Terlaris#

Untuk menghitung total unit produk yang terjual:

SELECT
pr.id_produk,
pr.nama_produk,
SUM(dp.jumlah) AS total_terjual
FROM produk pr
INNER JOIN detail_pesanan dp
ON pr.id_produk = dp.id_produk
GROUP BY
pr.id_produk,
pr.nama_produk
ORDER BY total_terjual DESC;

Hasil contoh:

ProdukUnit Terjual
Mouse Wireless2
Keyboard Mechanical1
Monitor 24 Inch1

Tetapi jika ingin mencari produk dengan nilai penjualan terbesar, gunakan:

SELECT
pr.id_produk,
pr.nama_produk,
SUM(dp.jumlah) AS total_unit,
SUM(dp.jumlah * dp.harga_satuan) AS total_nilai
FROM produk pr
INNER JOIN detail_pesanan dp
ON pr.id_produk = dp.id_produk
GROUP BY
pr.id_produk,
pr.nama_produk
ORDER BY total_nilai DESC;

Dalam data latihan, Monitor 24 Inch menghasilkan nilai penjualan terbesar.

Ingat bahwa “produk terlaris” dapat memiliki arti berbeda tergantung metrik yang digunakan.

Langkah 14 — Menghitung Total Nilai Penjualan#

Sekarang kita ingin mengetahui total nilai seluruh detail pembelian.

SELECT
COALESCE(
SUM(jumlah * harga_satuan),
0
) AS total_penjualan
FROM detail_pesanan;

Jika hanya ada dua transaksi dari tutorial ini, hasilnya:

2245000.00

Nilai tersebut berasal dari:

Andi = 595000
Budi = 1650000
----------------
Total = 2245000

Pada studi kasus ini, nilai tersebut merupakan total nominal pembelian yang tercatat.

Dalam aplikasi nyata, perhitungan omzet final biasanya perlu memperhatikan status pembayaran, pembatalan, retur, diskon, pajak, dan aturan bisnis lainnya.

Langkah 15 — Menggunakan HAVING#

Sekarang kita ingin menampilkan pelanggan dengan total pembelian lebih dari Rp500.000.

SELECT
pl.id_pelanggan,
pl.nama_pelanggan,
SUM(dp.jumlah * dp.harga_satuan) AS total_pembelian
FROM pelanggan pl
INNER JOIN pesanan p
ON pl.id_pelanggan = p.id_pelanggan
INNER JOIN detail_pesanan dp
ON p.id_pesanan = dp.id_pesanan
GROUP BY
pl.id_pelanggan,
pl.nama_pelanggan
HAVING SUM(dp.jumlah * dp.harga_satuan) > 500000
ORDER BY total_pembelian DESC;

Pada data latihan, Andi dan Budi memenuhi kondisi tersebut.

HAVING digunakan karena kita memfilter hasil perhitungan agregasi.

Langkah 16 — Menggunakan Subquery#

Kita ingin mencari produk yang harganya lebih tinggi dari rata-rata harga produk.

SELECT
id_produk,
nama_produk,
harga
FROM produk
WHERE harga > (
SELECT AVG(harga)
FROM produk
)
ORDER BY harga DESC;

Subquery menghitung rata-rata harga seluruh produk.

Query luar kemudian menampilkan produk yang harganya melebihi nilai tersebut.

Kita juga dapat mencari pelanggan yang belum pernah membuat pesanan menggunakan NOT EXISTS.

SELECT
pl.id_pelanggan,
pl.nama_pelanggan
FROM pelanggan pl
WHERE NOT EXISTS (
SELECT 1
FROM pesanan p
WHERE p.id_pelanggan = pl.id_pelanggan
);

Pada data contoh, hasilnya adalah Citra dan Dina.

Langkah 17 — Memeriksa Index dan EXPLAIN#

Kita sudah membuat index pada nama produk dan index gabungan pada pesanan.

Periksa:

SHOW INDEX FROM produk;
SHOW INDEX FROM pesanan;

Sekarang gunakan EXPLAIN:

EXPLAIN
SELECT
id_produk,
nama_produk,
harga
FROM produk
WHERE nama_produk = 'Keyboard Mechanical';

Perhatikan kolom possible_keys, key, type, dan rows.

Jika index tidak digunakan, bukan berarti ada kesalahan.

Tabel kita masih sangat kecil, sehingga optimizer mungkin memilih membaca seluruh tabel.

Index biasanya lebih terasa manfaatnya ketika jumlah data dan pola pencarian memang mendukung penggunaannya.

Langkah 18 — Memeriksa Stok Setelah Transaksi#

Kita juga perlu memastikan stok berubah sesuai transaksi.

SELECT
nama_produk,
stok
FROM produk
ORDER BY id_produk;

Jika mengikuti data awal dan kedua transaksi berhasil, stok yang diharapkan adalah:

ProdukStok Akhir
Keyboard Mechanical19
Mouse Wireless23
Monitor 24 Inch7
USB Flashdisk 64GB40
Headset Gaming12

Keyboard berkurang satu.

Mouse berkurang dua.

Monitor berkurang satu.

Produk lainnya tidak berubah.

Jika hasilnya berbeda, periksa apakah transaksi pernah dijalankan lebih dari sekali atau ada perubahan data tambahan.

Langkah 19 — Memahami Batasan Database yang Kita Buat#

Database toko online ini sudah mempunyai fondasi relasional yang cukup baik untuk latihan.

Namun, masih ada beberapa hal yang belum kita implementasikan.

Validasi Data#

Kita belum menambahkan semua aturan untuk mencegah nilai tidak valid.

Misalnya, jumlah pembelian seharusnya lebih dari nol.

Harga dan stok juga seharusnya tidak negatif.

Pada MySQL 8.0.16 atau lebih baru, kita dapat mempertimbangkan CHECK constraint.

Contohnya:

ALTER TABLE detail_pesanan
ADD CONSTRAINT chk_detail_jumlah
CHECK (jumlah > 0);
ALTER TABLE produk
ADD CONSTRAINT chk_produk_stok
CHECK (stok >= 0);

Perintah tersebut akan gagal jika data yang sudah ada melanggar aturan.

Karena itu, periksa data sebelum menambahkan constraint pada database yang sudah digunakan.

Status Pembayaran#

Tabel pesanan saat ini hanya mempunyai status sederhana.

Dalam aplikasi nyata, biasanya diperlukan informasi pembayaran, metode pembayaran, dan status pembayaran yang lebih rinci.

Pengiriman#

Kita belum menyimpan alamat pengiriman, jasa pengiriman, atau nomor resi.

Perubahan Harga dan Diskon#

Kita sudah menyimpan harga satuan pada detail transaksi.

Namun, belum ada sistem diskon, voucher, pajak, dan perhitungan total akhir yang lebih kompleks.

Audit dan Riwayat Perubahan#

Aplikasi yang lebih besar mungkin membutuhkan catatan perubahan data, pengguna yang melakukan perubahan, serta waktu perubahan.

Keamanan Akses#

Aplikasi produksi perlu menggunakan akun database dengan hak akses yang sesuai, query berparameter, pengelolaan kredensial yang aman, backup, dan pengawasan aktivitas.

Jangan menggunakan akun database dengan hak administrator untuk seluruh operasi aplikasi.

Semua hal tersebut dapat dikembangkan secara bertahap.

Tujuan studi kasus ini adalah memahami fondasi database, bukan langsung membangun marketplace berskala besar.

Latihan Akhir Series#

Sekarang kita akan menguji pemahaman dari Bab 1 sampai Bab 8.

Coba kerjakan latihan berikut menggunakan database db_toko_bapakgabut_final.

Latihan 1 — Tambahkan Produk Baru#

Tambahkan produk:

  • Nama: Webcam HD.
  • Harga: Rp225.000.
  • Stok: 10.

Kemudian tampilkan seluruh produk.

Latihan 2 — Tambahkan Pelanggan Baru#

Tambahkan pelanggan:

  • Nama: Eko.
  • Email: eko@example.com.
  • Tanggal daftar: 2026-10-10.

Latihan 3 — Buat Transaksi Pembelian#

Buat transaksi pembelian untuk Eko:

  • Produk: Webcam HD.
  • Jumlah: 2.
  • Harga satuan: Rp225.000.

Gunakan transaction.

Pastikan stok tersedia sebelum membuat pesanan.

Jika seluruh langkah berhasil, lakukan COMMIT.

Jika ada kegagalan, lakukan ROLLBACK.

Latihan 4 — Buat Laporan Penjualan#

Buat query untuk menampilkan:

  • Nama pelanggan.
  • Jumlah pesanan.
  • Total pembelian.

Urutkan berdasarkan total pembelian terbesar.

Latihan 5 — Cari Produk yang Belum Pernah Terjual#

Buat query untuk menampilkan produk yang belum pernah muncul pada tabel detail pesanan.

Gunakan NOT EXISTS atau LEFT JOIN.

Coba kerjakan sendiri terlebih dahulu sebelum melihat pembahasannya.

Pembahasan Latihan Akhir#

Jawaban Latihan 1#

INSERT INTO produk (
nama_produk,
harga,
stok
)
VALUES (
'Webcam HD',
225000,
10
);

Periksa:

SELECT *
FROM produk
ORDER BY id_produk;

Jawaban Latihan 2#

INSERT INTO pelanggan (
nama_pelanggan,
email,
tanggal_daftar
)
VALUES (
'Eko',
'eko@example.com',
'2026-10-10'
);

Periksa:

SELECT *
FROM pelanggan
WHERE email = 'eko@example.com';

Jawaban Latihan 3#

Pertama, ambil ID:

SET @id_eko = (
SELECT id_pelanggan
FROM pelanggan
WHERE email = 'eko@example.com'
);
SET @id_webcam = (
SELECT id_produk
FROM produk
WHERE nama_produk = 'Webcam HD'
LIMIT 1
);

Pastikan kedua ID tersedia:

SELECT
@id_eko AS id_eko,
@id_webcam AS id_webcam;

Mulai transaksi:

START TRANSACTION;

Kunci produk:

SELECT
id_produk,
nama_produk,
stok
FROM produk
WHERE id_produk = @id_webcam
FOR UPDATE;

Pastikan stok minimal dua.

Jika tidak mencukupi, jalankan ROLLBACK dan hentikan proses.

Buat pesanan:

INSERT INTO pesanan (
id_pelanggan,
status_pesanan
)
VALUES (
@id_eko,
'baru'
);

Ambil ID pesanan:

SET @id_pesanan_eko = LAST_INSERT_ID();

Tambahkan detail:

INSERT INTO detail_pesanan (
id_pesanan,
id_produk,
jumlah,
harga_satuan
)
VALUES (
@id_pesanan_eko,
@id_webcam,
2,
225000
);

Kurangi stok:

UPDATE produk
SET stok = stok - 2
WHERE id_produk = @id_webcam
AND stok >= 2;

Segera periksa:

SELECT ROW_COUNT() AS jumlah_baris_diubah;

Jika hasilnya 1 dan seluruh langkah sebelumnya berhasil, jalankan:

COMMIT;

Jika ada kegagalan:

ROLLBACK;

Setelah transaksi berhasil, stok Webcam HD seharusnya berkurang dari 10 menjadi 8.

Jawaban Latihan 4#

SELECT
pl.id_pelanggan,
pl.nama_pelanggan,
COUNT(DISTINCT p.id_pesanan) AS jumlah_pesanan,
COALESCE(
SUM(dp.jumlah * dp.harga_satuan),
0
) AS total_pembelian
FROM pelanggan pl
LEFT JOIN pesanan p
ON pl.id_pelanggan = p.id_pelanggan
LEFT JOIN detail_pesanan dp
ON p.id_pesanan = dp.id_pesanan
GROUP BY
pl.id_pelanggan,
pl.nama_pelanggan
ORDER BY total_pembelian DESC;

Jawaban Latihan 5#

SELECT
pr.id_produk,
pr.nama_produk
FROM produk pr
WHERE NOT EXISTS (
SELECT 1
FROM detail_pesanan dp
WHERE dp.id_produk = pr.id_produk
);

Query tersebut menampilkan produk yang belum pernah tercatat dalam detail pembelian.

Jika kamu sudah menyelesaikan seluruh latihan, berarti kamu sudah mempraktikkan sebagian besar konsep utama dari series ini.

Apa Langkah Selanjutnya Setelah Belajar MySQL?#

Setelah memahami dasar MySQL, ada beberapa arah pembelajaran yang bisa kamu lanjutkan.

Pertama, belajar backend API.

Kamu dapat membuat aplikasi menggunakan Node.js dan Express, lalu menghubungkannya ke MySQL.

Dengan begitu, query yang sebelumnya dijalankan secara manual melalui DBeaver dapat digunakan oleh aplikasi.

Kedua, belajar desain database yang lebih kompleks.

Misalnya, menambahkan tabel pembayaran, alamat pengiriman, riwayat stok, dan audit log.

Ketiga, memperdalam optimasi database.

Kamu bisa mempelajari index, execution plan, locking, isolation level, dan strategi pengelolaan query pada data yang lebih besar.

Keempat, belajar keamanan database.

Pelajari prepared statement, pembatasan hak akses, backup, pemulihan data, dan pengelolaan kredensial.

Database bukan hanya soal menyimpan data.

Database juga tentang bagaimana menjaga data tetap benar, mudah diakses, aman, dan dapat digunakan ketika kebutuhan aplikasi berkembang.

Penutup Series Belajar Database MySQL dari Nol#

Kita sudah menyelesaikan delapan bab:

  1. Apa Itu Database? Mengenal Database, DBMS, dan MySQL.
  2. Cara Install MySQL dan Menghubungkannya ke DBeaver.
  3. Belajar SQL Dasar: CREATE TABLE, Tipe Data, dan Primary Key.
  4. Belajar SQL CRUD: INSERT, SELECT, UPDATE, dan DELETE.
  5. Relasi Tabel MySQL: Foreign Key dan JOIN.
  6. Query SQL Lanjutan: GROUP BY, HAVING, dan Subquery.
  7. Index dan Transaction MySQL: Bikin Query Lebih Efisien dan Aman.
  8. Studi Kasus MySQL: Membuat Database Toko Online Sederhana.

Dari awalnya hanya mengenal istilah database, sekarang kita sudah bisa membuat struktur tabel, menghubungkan data, mencatat transaksi, dan menghasilkan laporan.

Tentu perjalanan belajar database tidak berhenti di sini.

Masih banyak hal yang bisa dipelajari, terutama ketika kita mulai menghubungkan database dengan aplikasi backend dan frontend.

Namun, dengan fondasi yang sudah dibangun selama delapan bab ini, kita mempunyai bekal untuk melanjutkan ke tahap berikutnya.

Terima kasih sudah mengikuti Series Database BapakGabut sampai selesai.

Semoga tutorial ini membantu kamu memahami MySQL dengan cara yang lebih praktis dan tidak terlalu membingungkan.

Sampai jumpa di series berikutnya, Gabuters!

Bagian 8 dari 8Tulisan ini bagian dari seri

Bagikan Artikel

Buat poster berbagi atau salin tautan artikel ini.

Lanjut membaca

Bacaan terkait

Berdasarkan tag dan kategori yang sama

Coba jalur lain

Pilihan konsisten dari artikel lain