INSERTINTO tabel (k1, k2) VALUES (v1, v2), (v3, v4); SELECT k1, k2 FROM tabel WHERE kondisi ORDERBY k1 LIMIT 10; UPDATE tabel SET k1 = v1 WHERE kondisi; DELETEFROM tabel WHERE kondisi;
JOIN
1 2 3 4 5 6
-- INNER JOIN SELECT*FROM t1 INNERJOIN t2 ON t1.id = t2.id_t1; -- LEFT JOIN SELECT*FROM t1 LEFTJOIN t2 ON t1.id = t2.id_t1; -- Multi-table SELECT*FROM t1 JOIN t2 ON ... JOIN t3 ON ...;
Stored Procedure & Trigger
1 2 3 4 5 6 7 8 9 10
DELIMITER // CREATEPROCEDURE sp_nama(IN p1 INT, OUT p2 VARCHAR(100)) BEGIN -- logika END// CREATETRIGGER trg_nama AFTER INSERTON tabel FOREACHROWBEGIN-- END // DELIMITER ;
CALL sp_nama(1, @hasil); SELECT@hasil;
GROUP BY + HAVING + ORDER BY
1 2 3 4 5 6
SELECT kolom, COUNT(*), AVG(nilai) FROM tabel WHERE kondisi GROUPBY kolom HAVINGCOUNT(*) >1 ORDERBY kolom DESC;
INDEX
1 2 3 4 5
CREATE INDEX idx_nama ON tabel(kolom); CREATEUNIQUE INDEX idx_uniq ON tabel(kolom); SHOW INDEX FROM tabel; EXPLAIN SELECT*FROM tabel WHERE kolom ='nilai'; DROP INDEX idx_nama ON tabel;
π Backup & Restore MySQL dengan mysqldump
Backup Database
mysqldump adalah tools bawaan MySQL untuk backup database via command line.
# Backup hanya struktur (tanpa data) mysqldump -u root -p --no-data db_perpustakaan > struktur_perpustakaan.sql
# Backup hanya data (tanpa struktur) mysqldump -u root -p --no-create-info db_perpustakaan > data_perpustakaan.sql
# Backup tabel tertentu saja mysqldump -u root -p db_perpustakaan buku anggota > backup_partial.sql
Restore Database
1 2 3 4 5 6
# Restore dari file backup mysql -u root -p db_perpustakaan < backup_perpustakaan.sql
# Jika database belum ada, buat dulu mysql -u root -p -e "CREATE DATABASE db_perpustakaan_restore;" mysql -u root -p db_perpustakaan_restore < backup_perpustakaan.sql
-- Lihat query CREATE TABLE saat ini SHOWCREATETABLE buku; SHOWCREATETABLE anggota;
-- MySQL tidak punya perintah BACKUP langsung seperti SQL Server -- Gunakan mysqldump dari terminal, atau gunakan phpMyAdmin / MySQL Workbench -- untuk export/import dengan GUI
-- Alternatif: SELECT INTO OUTFILE (export ke CSV) SELECT*FROM buku INTO OUTFILE '/tmp/buku_export.csv' FIELDS TERMINATED BY',' ENCLOSED BY'"' LINES TERMINATED BY'\n';
-- Import dari CSV -- LOAD DATA INFILE '/tmp/buku_export.csv' -- INTO TABLE buku -- FIELDS TERMINATED BY ',' -- ENCLOSED BY '"' -- LINES TERMINATED BY '\n';
-- 1. INSERT dengan SELECT (copy data) -- Buat tabel backup buku CREATETABLE buku_arsip LIKE buku; INSERTINTO buku_arsip SELECT*FROM buku WHERE tahun_terbit <2000; SELECT*FROM buku_arsip;
-- 2. UPDATE dengan JOIN UPDATE buku b JOIN kategori k ON b.id_kategori = k.id_kategori SET b.harga = b.harga *1.10 WHERE k.nama_kat ='Teknologi';
-- 3. DELETE dengan subquery -- Hapus log aktivitas yang lebih dari 30 hari lalu -- DELETE FROM log_aktivitas WHERE waktu < DATE_SUB(NOW(), INTERVAL 30 DAY);
-- 4. SELECT dengan subquery -- Tampilkan buku yang harganya di atas rata-rata SELECT judul, harga FROM buku WHERE harga > (SELECTAVG(harga) FROM buku) ORDERBY harga DESC;
-- 5. SELECT dengan EXISTS -- Anggota yang sudah pernah meminjam minimal satu buku SELECT nama, email FROM anggota a WHEREEXISTS ( SELECT1FROM peminjaman p WHERE p.id_anggota = a.id_anggota );
-- 6. Multi-level JOIN dengan CASE SELECT a.nama AS anggota, COUNT(p.id_pinjam) AS total_pinjam, CASE WHENCOUNT(p.id_pinjam) >=5THEN'Platinum' WHENCOUNT(p.id_pinjam) >=3THEN'Gold' WHENCOUNT(p.id_pinjam) >=1THEN'Silver' ELSE'Baru' ENDAS level_member FROM anggota a LEFTJOIN peminjaman p ON a.id_anggota = p.id_anggota GROUPBY a.id_anggota, a.nama ORDERBY total_pinjam DESC;
π§βπ» LATIHAN 2 β Review Stored Procedure Lanjutan
-- Procedure: laporan peminjaman per periode CREATEPROCEDURE sp_laporan_periode( IN p_dari DATE, IN p_sampai DATE ) BEGIN SELECT a.nama AS anggota, b.judul AS buku, p.tgl_pinjam, p.tgl_kembali, p.status, DATEDIFF(COALESCE(p.tgl_kembali_aktual, CURDATE()), p.tgl_pinjam) AS lama_hari FROM peminjaman p JOIN anggota a ON p.id_anggota = a.id_anggota JOIN buku b ON p.id_buku = b.id_buku WHERE p.tgl_pinjam BETWEEN p_dari AND p_sampai ORDERBY p.tgl_pinjam;
-- Summary SELECT COUNT(*) AS total_transaksi, SUM(CASEWHEN p.status ='dipinjam'THEN1ELSE0END) AS masih_dipinjam, SUM(CASEWHEN p.status ='dikembalikan'THEN1ELSE0END) AS sudah_kembali, SUM(CASEWHEN p.status ='terlambat'THEN1ELSE0END) AS terlambat FROM peminjaman p WHERE p.tgl_pinjam BETWEEN p_dari AND p_sampai; END//
-- Procedure: top N anggota terbanyak pinjam CREATEPROCEDURE sp_top_anggota(IN p_top INT) BEGIN SELECT a.kode_ang, a.nama, a.email, COUNT(p.id_pinjam) AS total_pinjam, MAX(p.tgl_pinjam) AS terakhir_pinjam FROM anggota a JOIN peminjaman p ON a.id_anggota = p.id_anggota GROUPBY a.id_anggota, a.kode_ang, a.nama, a.email ORDERBY total_pinjam DESC LIMIT p_top; END//
DELIMITER ;
-- Test CALL sp_laporan_periode('2026-06-01', '2026-06-30'); CALL sp_top_anggota(3);
-- Trigger: otomatis update status buku berdasarkan stok CREATETRIGGER trg_after_update_stok AFTER UPDATEON buku FOREACHROW BEGIN IF NEW.stok =0AND OLD.stok >0THEN INSERTINTO log_aktivitas (tabel_terkait, aksi, id_record, keterangan) VALUES ('buku', 'UPDATE', NEW.id_buku, CONCAT('PERINGATAN: Stok buku "', NEW.judul, '" telah habis!')); END IF; END//
-- Trigger: validasi email format sebelum insert anggota CREATETRIGGER trg_before_insert_anggota BEFORE INSERTON anggota FOREACHROW BEGIN IF NEW.email ISNOTNULLAND NEW.email NOTLIKE'%@%.%'THEN SIGNAL SQLSTATE'45000' SET MESSAGE_TEXT ='Format email tidak valid!'; END IF; END//
DELIMITER ;
-- Test trigger validasi email -- Ini harus error: -- INSERT INTO anggota (kode_ang, nama, email) VALUES ('ANG100', 'Test', 'emailsalah');
-- Ini harus berhasil: INSERTINTO anggota (kode_ang, nama, email) VALUES ('ANG100', 'Test Anggota', '[email protected]');
-- Update stok jadi 0 untuk test trigger peringatan UPDATE buku SET stok =0WHERE id_buku =2; SELECT*FROM log_aktivitas ORDERBY id_log DESC LIMIT 5;
π§βπ» LATIHAN 4 β Quiz Review (Kerjakan Tanpa Melihat Catatan!)
-- QUIZ 1 (DDL): -- Buat tabel `rak_buku` dengan kolom: -- id_rak (PK, auto), kode_rak (UNIQUE, NOT NULL), lokasi (VARCHAR 100), kapasitas (INT, default 50) -- Tambahkan kolom `keterangan TEXT` ke tabel tersebut -- Lalu hapus kolom tersebut
-- QUIZ 2 (DML): -- Masukkan 3 rak buku -- Update kapasitas rak pertama menjadi 75 -- Hapus rak dengan kapasitas kurang dari 10
-- QUIZ 3 (SELECT lanjutan): -- Tampilkan nama anggota, judul buku, lama peminjaman, dan denda -- Untuk yang sudah melewati tanggal kembali dan masih berstatus 'dipinjam' -- Denda = Rp 1000 per hari keterlambatan
-- QUIZ 4 (GROUP BY): -- Tampilkan per bulan: jumlah peminjaman, jumlah unik anggota yang meminjam, -- dan jumlah buku unik yang dipinjam
-- QUIZ 5 (JOIN + CASE): -- Buat laporan buku dengan kolom: -- Judul, Penulis, Kategori, Total Dipinjam, Stok Saat Ini, -- Rekomendasi: 'Beli Lebih' jika total dipinjam > stok, 'Cukup' jika sebaliknya
π§ PROYEK AKHIR β Sistem Database Mini
Deskripsi
Bangun sebuah sistem database mini menggunakan MySQL dengan tema bebas. Proyek ini mengintegrasikan semua konsep yang telah dipelajari selama 6 pertemuan.
Pilihan Tema
Pilih salah satu atau ajukan tema sendiri ke instruktur:
-- a. Buat ERD terlebih dahulu (gambar di draw.io / MySQL Workbench / tulis tangan) -- b. Minimal 5 tabel yang saling terhubung -- c. Gunakan constraint lengkap: PK, FK, UNIQUE, NOT NULL, DEFAULT, CHECK -- d. Gunakan minimal 5 tipe data berbeda
-- Contoh skeleton untuk tema Toko Online: CREATE DATABASE db_toko_final; USE db_toko_final;
-- Minimal 10 data per tabel -- Data harus konsisten (FK harus merujuk ke data yang benar) -- Gunakan INSERT beberapa baris sekaligus
3. Query SELECT Kompleks (min. 10 query)
1 2 3 4 5 6 7 8 9
-- Wajib mencakup: -- a. SELECT dengan WHERE + multiple conditions (AND/OR/IN/BETWEEN/LIKE) -- b. INNER JOIN minimal 3 tabel -- c. LEFT JOIN untuk menemukan data yang tidak berelasi -- d. GROUP BY + HAVING -- e. ORDER BY multi-kolom -- f. Subquery (minimal 1) -- g. CASE WHEN dalam SELECT -- h. Aggregate functions (COUNT, SUM, AVG, MAX, MIN)
4. Stored Procedure (min. 3)
1 2 3 4 5 6 7 8 9 10 11 12 13 14
-- Contoh untuk tema Toko Online:
-- a. sp_proses_pesanan(IN id_pelanggan, IN id_produk, IN jumlah, OUT total, OUT pesan) -- - Cek stok produk -- - Kurangi stok jika tersedia -- - Buat record pesanan -- - Return total harga dan pesan sukses/gagal
-- b. sp_laporan_penjualan(IN dari_tgl DATE, IN sampai_tgl DATE) -- - Tampilkan semua transaksi dalam periode -- - Summary: total transaksi, total pendapatan, produk terlaris
-- c. sp_top_pelanggan(IN top_n INT) -- - Tampilkan N pelanggan dengan pembelian terbanyak
5. Trigger (min. 2)
1 2 3 4
-- Contoh: -- a. trg_kurangi_stok: otomatis kurangi stok saat pesanan baru masuk -- b. trg_log_perubahan: catat setiap perubahan harga produk ke tabel log -- c. trg_validasi_stok: tolak pesanan jika stok tidak cukup (BEFORE INSERT)
6. View (min. 2)
1 2 3
-- Contoh: -- a. v_laporan_lengkap: gabungan semua tabel untuk laporan transaksi -- b. v_stok_produk: status stok setiap produk beserta keterangannya
7. Index (min. 3)
1 2
-- Buat index pada kolom yang sering digunakan di WHERE dan JOIN -- Gunakan EXPLAIN untuk membuktikan efektivitas index
8. Backup Database
1 2
# Jalankan dari terminal, sertakan hasilnya dalam laporan mysqldump -u root -p db_toko_final > backup_db_toko_final_2026.sql
-- ============================================================ -- PROYEK AKHIR DATABASE MYSQL -- Nama : [Nama Kamu] -- Tema : [Tema yang dipilih] -- Tanggal: [Tanggal] -- ============================================================
-- ===================== -- BAGIAN 1: DDL (CREATE) -- =====================
-- ===================== -- BAGIAN 2: DML (INSERT) -- =====================
-- ===================== -- BAGIAN 3: QUERY SELECT -- =====================
-- ===================== -- BAGIAN 4: STORED PROCEDURE -- =====================
-- ===================== -- BAGIAN 5: TRIGGER -- =====================
-- ===================== -- BAGIAN 6: VIEW -- =====================
-- ===================== -- BAGIAN 7: INDEX -- =====================
-- 1. TRANSACTION: gunakan COMMIT dan ROLLBACK untuk operasi yang memerlukan atomicity START TRANSACTION; -- Operasi 1 -- Operasi 2 -- Jika ada error: ROLLBACK; -- Jika sukses: COMMIT;
-- 2. FUNCTION KUSTOM: buat fungsi sendiri (bukan procedure) DELIMITER // CREATEFUNCTION fn_format_rupiah(jumlah DECIMAL(15,2)) RETURNSVARCHAR(50) DETERMINISTIC BEGIN RETURN CONCAT('Rp ', FORMAT(jumlah, 0, 'id_ID')); END// DELIMITER ;
-- Test SELECT fn_format_rupiah(1500000); -- Output: Rp 1.500.000
-- 3. SUBQUERY LANJUTAN -- Tampilkan produk yang lebih mahal dari rata-rata harga di kategorinya SELECT p.nama, p.harga, k.nama_kat FROM produk p JOIN kategori_produk k ON p.id_kategori = k.id_kategori WHERE p.harga > ( SELECTAVG(p2.harga) FROM produk p2 WHERE p2.id_kategori = p.id_kategori );
π Refleksi Akhir
Jawab pertanyaan berikut sebagai penutup course:
Konsep SQL apa yang menurut kamu paling sulit? Mengapa?
Kapan kamu memilih menggunakan Stored Procedure dibanding menjalankan query langsung dari aplikasi?
Apa 3 hal yang harus diperhatikan agar database berjalan efisien?
Mengapa backup database itu penting? Seberapa sering idealnya dilakukan?
Apa perbedaan utama antara MySQL dan SQL Server yang kamu rasakan?