1. Latar Belakang
Setelah mempelajari trigger untuk audit trail, hari ini kita akan fokus pada penggunaan trigger untuk validasi otomatis dan otomasi logika bisnis. Ini adalah "kulkas pintar" yang tidak hanya merekam, tapi juga bisa berpikir dan bertindak sendiri!
Apa itu Validasi Otomatis?
Validasi otomatis adalah proses pengecekan data secara otomatis oleh database sebelum data tersebut disimpan atau diubah. Ibarat satpam di pintu masuk mall yang memeriksa semua pengunjung sebelum boleh masuk.
Apa itu Otomasi Bisnis?
Otomasi bisnis adalah proses di mana database secara otomatis menjalankan aturan-aturan bisnis tanpa perlu campur tangan aplikasi. Ibarat eskalator yang otomatis jalan ketika ada orang yang mendekat.
Kenapa Penting?
- Mencegah data kotor masuk ke database
- Menegakkan aturan bisnis secara konsisten
- Mengurangi beban backend developer
- Memastikan kepatuhan terhadap regulasi
- Mengotomatiskan tugas-tugas repetitif
Di database plc_trigger_practice, kita punya banyak contoh validasi dan otomasi:
cek_stok_sebelum_order- Validasi stok sebelum ordervalidasi_gaji_sebelum_update- Aturan kompleks penggajiancek_karyawan_sebelum_insert- Validasi data karyawan barucek_stok_buku_sebelum_pinjam- Validasi stok perpustakaanvalidasi_pengembalian_buku- Validasi tanggal kembali
2. Alat dan Bahan
a. Perangkat Lunak
- MySQL - Database dengan trigger yang sudah ada
- Database
plc_trigger_practice- Berisi tabel dan trigger - MySQL Workbench / phpMyAdmin - Untuk menjalankan query
- VS Code - Untuk menulis dan dokumentasi
b. Perangkat Keras
- Laptop/PC dengan spesifikasi standar
3. Pembahasan
3.1 Konsep Validasi dengan Trigger
Bagainiana Trigger Bisa Melakukan Validasi?
┌──────────────┐
│ APLIKASI │
│ (User/Sistem)│
└──────┬───────┘
│ INSERT INTO orders
│ (product_id=1, jumlah=100)
▼
┌────────────────────────────────────┐
│ DATABASE │
├────────────────────────────────────┤
│ 🔥 BEFORE INSERT TRIGGER │
│ ┌────────────────────────────┐ │
│ │ "Cek stok dulu..." │ │
│ │ │ │
│ │ SELECT stok FROM products │ │
│ │ WHERE id = NEW.product_id │ │
│ │ │ │
│ │ IF stok < NEW.jumlah THEN │ │
│ │ SIGNAL SQLSTATE '...' │ │
│ │ "Stok tidak cukup!" │ │
│ │ END IF; │ │
│ └────────────┬───────────────┘ │
│ │ Lolos validasi │
│ ▼ │
│ ┌────────────────────────────┐ │
│ │ INSERT ke tabel orders │ │
│ │ (Data tersimpan) │ │
│ └────────────────────────────┘ │
└────────────────────────────────────┘3.2 BEFORE vs AFTER untuk Validasi
| Jenis Trigger | Cocok untuk Validasi? | Kenapa? |
|---|---|---|
| BEFORE | ✅ SANGAT COCOK | Bisa mencegah data masuk dengan SIGNAL |
| AFTER | ❌ TIDAK COCOK | Data sudah terlanjur masuk, tidak bisa dibatalkan |
Aturan Emas:
Semua validasi HARUS menggunakan BEFORE trigger!
3.3 Studi Kasus 1: Validasi Stok Sebelum Order
Mari kita bedah trigger cek_stok_sebelum_order:
DELIMITER $$
CREATE TRIGGER cek_stok_sebelum_order
BEFORE INSERT ON orders
FOR EACH ROW
BEGIN
DECLARE stok_tersedia INT;
DECLARE harga_product DECIMAL(10,2);
-- Ambil stok dan harga produk
SELECT stok, harga INTO stok_tersedia, harga_product
FROM products
WHERE id = NEW.product_id;
-- Validasi 1: Stok cukup?
IF stok_tersedia < NEW.jumlah THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Stok tidak cukup, bro!';
END IF;
-- Validasi 2: Jumlah order tidak boleh 0 atau negatif
IF NEW.jumlah <= 0 THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Jumlah order harus lebih dari 0!';
END IF;
-- Otomasi: Hitung total harga otomatis
SET NEW.total_harga = harga_product * NEW.jumlah;
-- Otomasi: Set default customer name jika tidak diisi
IF NEW.customer_name IS NULL OR NEW.customer_name = '' THEN
SET NEW.customer_name = 'Guest Customer';
END IF;
END$$
DELIMITER ;Apa yang dilakukan trigger ini?
| Fungsi | Jenis | Penjelasan |
|---|---|---|
| Cek stok cukup | Validasi | Mencegah order melebihi stok |
| Cek jumlah > 0 | Validasi | Mencegah order 0 atau negatif |
| Hitung total harga | Otomasi | Mengisi total_harga otomatis |
| Set default customer | Otomasi | Mengisi customer_name jika kosong |
Demo Skenario 1: Order dengan stok cukup
-- Lihat stok laptop (id=1) = 10
SELECT * FROM products WHERE id = 1;
-- Order 2 laptop (stok cukup)
INSERT INTO orders (product_id, jumlah, customer_name)
VALUES (1, 2, 'Budi Santoso');
-- Berhasil! Cek total_harga terisi otomatis: 2 * 15.000.000 = 30.000.000
SELECT * FROM orders ORDER BY id DESC LIMIT 1;Demo Skenario 2: Order melebihi stok
-- Order 20 laptop (stok cuma 10)
INSERT INTO orders (product_id, jumlah, customer_name)
VALUES (1, 20, 'Toko Besar');
-- ERROR! Stok tidak cukup, bro!
-- Data TIDAK MASUK ke databaseDemo Skenario 3: Order dengan jumlah 0
-- Order 0 laptop
INSERT INTO orders (product_id, jumlah, customer_name)
VALUES (1, 0, 'Iseng Doang');
-- ERROR! Jumlah order harus lebih dari 0!Demo Skenario 4: Customer name kosong
-- Tidak isi customer_name
INSERT INTO orders (product_id, jumlah)
VALUES (2, 3);
-- Berhasil! customer_name otomatis jadi 'Guest Customer'
SELECT * FROM orders ORDER BY id DESC LIMIT 1;3.4 Studi Kasus 2: Validasi Data Karyawan Baru
Trigger cek_karyawan_sebelum_insert:
DELIMITER $$
CREATE TRIGGER cek_karyawan_sebelum_insert
BEFORE INSERT ON karyawan
FOR EACH ROW
BEGIN
-- Validasi 1: Gaji tidak boleh negatif
IF NEW.gaji < 0 THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Gaji gaboleh minus, mas!';
END IF;
-- Validasi 2: Gaji minimal 4 juta (UMR)
IF NEW.gaji < 4000000 THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Gaji minimal Rp 4.000.000!';
END IF;
-- Validasi 3: Umur minimal 17 tahun
IF TIMESTAMPDIFF(YEAR, NEW.tanggal_lahir, CURDATE()) < 17 THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Umur minimal 17 tahun!';
END IF;
-- Validasi 4: Nama tidak boleh kosong
IF NEW.nama IS NULL OR TRIM(NEW.nama) = '' THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Nama karyawan wajib diisi!';
END IF;
-- Otomasi: Format nama (capitalize first letter of each word)
-- Catatan: Ini contoh, implementasi sebenarnya lebih kompleks
SET NEW.nama = CONCAT(
UPPER(SUBSTRING(NEW.nama, 1, 1)),
LOWER(SUBSTRING(NEW.nama, 2))
);
END$$
DELIMITER ;Aturan Validasi:
| Aturan | Kenapa Penting? |
|---|---|
| Gaji tidak boleh negatif | Logika dasar, gaji masa minus? |
| Gaji minimal 4 juta | Sesuai aturan UMR/UMK |
| Umur minimal 17 tahun | Syarat legal bekerja |
| Nama wajib diisi | Data karyawan harus lengkap |
Demo Skenario 1: Karyawan baru valid
-- Coba insert karyawan baru
INSERT INTO karyawan (nama, gaji, jabatan, tanggal_lahir, departemen)
VALUES ('febri hariyanto', 5000000, 'Staff IT', '2000-05-15', 'IT');
-- Berhasil! Nama otomatis jadi 'Febri hariyanto' (huruf pertama kapital)
SELECT * FROM karyawan ORDER BY id DESC LIMIT 1;Demo Skenario 2: Gaji di bawah UMR
-- Coba insert dengan gaji 3 juta
INSERT INTO karyawan (nama, gaji, jabatan, tanggal_lahir, departemen)
VALUES ('Test Karyawan', 3500000, 'Staff', '2000-01-01', 'HR');
-- ERROR! Gaji minimal Rp 4.000.000!Demo Skenario 3: Umur di bawah 17 tahun
-- Coba insert karyawan umur 16 tahun
INSERT INTO karyawan (nama, gaji, jabatan, tanggal_lahir, departemen)
VALUES ('Bocil Koding', 4500000, 'Intern', '2010-01-01', 'IT');
-- ERROR! Umur minimal 17 tahun!3.5 Studi Kasus 3: Validasi Kompleks Penggajian
Trigger validasi_gaji_sebelum_update - ini adalah contoh validasi paling kompleks di database kita:
DELIMITER $$
CREATE TRIGGER validasi_gaji_sebelum_update
BEFORE UPDATE ON karyawan
FOR EACH ROW
BEGIN
DECLARE gaji_direktur DECIMAL(10,2);
DECLARE gaji_manager_departemen DECIMAL(10,2);
DECLARE max_kenaikan DECIMAL(10,2);
DECLARE rata_gaji_sejenis DECIMAL(10,2);
-- ============================================
-- VALIDASI 1: Kenaikan gaji maksimal 20%
-- ============================================
SET max_kenaikan = OLD.gaji * 1.2;
IF NEW.gaji > max_kenaikan THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = '❌ Kenaikan gaji maksimal 20% aja, santuy!';
END IF;
-- ============================================
-- VALIDASI 2: Gaji manager tidak boleh > direktur
-- ============================================
IF NEW.jabatan LIKE '%Manager%' AND NEW.jabatan != 'Direktur' THEN
-- Cari gaji direktur
SELECT gaji INTO gaji_direktur
FROM karyawan
WHERE jabatan = 'Direktur'
LIMIT 1;
-- Jika ketemu dan gaji manager > direktur
IF gaji_direktur IS NOT NULL AND NEW.gaji > gaji_direktur THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = '❌ Gaji manager gaboleh lebih gede dari direktur!';
END IF;
END IF;
-- ============================================
-- VALIDASI 3: Gaji staff maksimal 80% dari manager
-- ============================================
IF NEW.jabatan LIKE '%Staff%' THEN
SELECT AVG(gaji) INTO gaji_manager_departemen
FROM karyawan
WHERE jabatan LIKE '%Manager%'
AND departemen = NEW.departemen;
IF gaji_manager_departemen IS NOT NULL AND
NEW.gaji > gaji_manager_departemen * 0.8 THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = '❌ Gaji staff maksimal 80% dari gaji manager di departemen yang sama!';
END IF;
END IF;
-- ============================================
-- VALIDASI 4: Gaji tidak boleh turun (kecuali demosi)
-- ============================================
IF NEW.gaji < OLD.gaji AND NEW.jabatan = OLD.jabatan THEN
-- Jika jabatan sama tapi gaji turun, TOLAK!
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = '❌ Gaji tidak boleh turun jika jabatan sama!';
END IF;
-- ============================================
-- VALIDASI 5: Gaji baru tidak boleh melebihi budget departemen
-- ============================================
IF NEW.departemen IS NOT NULL THEN
DECLARE total_gaji_departemen DECIMAL(10,2);
DECLARE budget_departemen DECIMAL(10,2);
-- Hitung total gaji di departemen (termasuk yang baru)
SELECT SUM(gaji) INTO total_gaji_departemen
FROM karyawan
WHERE departemen = NEW.departemen AND id != NEW.id;
SET total_gaji_departemen = IFNULL(total_gaji_departemen, 0) + NEW.gaji;
-- Budget departemen (contoh: 100 juta per departemen)
-- Dalam real case, ini bisa dari tabel budget
SET budget_departemen = 100000000;
IF total_gaji_departemen > budget_departemen THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = '❌ Total gaji departemen melebihi budget!';
END IF;
END IF;
END$$
DELIMITER ;5 Aturan Validasi yang Dijalankan:
| Aturan | Deskripsi | Contoh Pelanggaran |
|---|---|---|
| Rule 1 | Kenaikan maksimal 20% | Gaji 10jt → 13jt (30%) |
| Rule 2 | Manager ≤ Direktur | Manager 30jt, Direktur 25jt |
| Rule 3 | Staff ≤ 80% Manager | Staff 10jt, Manager 11jt (91%) |
| Rule 4 | Gaji tidak boleh turun | 10jt → 9jt (jabatan sama) |
| Rule 5 | Tidak melebihi budget departemen | Total gaji dept > 100jt |
Demo Skenario 1: Kenaikan wajar (15%)
-- Lihat gaji Budi (id=1) = 8.5jt
SELECT * FROM karyawan WHERE id = 1;
-- Naikkan 15% (8.5jt → 9.775jt) - MASIH AMAN
UPDATE karyawan
SET gaji = 9775000
WHERE id = 1;
-- BERHASIL! Masih di bawah 20%Demo Skenario 2: Kenaikan terlalu tinggi (30%)
-- Naikkan 30% (8.5jt → 11.05jt)
UPDATE karyawan
SET gaji = 11050000
WHERE id = 1;
-- ERROR! Kenaikan gaji maksimal 20% aja, santuy!
-- Data TIDAK JADI diupdateDemo Skenario 3: Manager minta gaji lebih dari direktur
-- Lihat gaji direktur (Rudi? Cek dulu)
SELECT * FROM karyawan WHERE jabatan = 'Direktur';
-- Coba naikkan gaji manager (Siti, id=2) di atas direktur
UPDATE karyawan
SET gaji = 35000000
WHERE id = 2;
-- ERROR! Gaji manager gaboleh lebih gede dari direktur!Demo Skenario 4: Staff minta gaji hampir sama dengan manager
-- Coba naikkan gaji staff (Dewi, id=4) jadi 10jt
-- Manager departemen Finance (Maya, id=8) gaji 18jt
-- 10jt adalah 55.5% dari 18jt (MASIH AMAN, di bawah 80%)
UPDATE karyawan
SET gaji = 10000000
WHERE id = 4;
-- BERHASIL! Masih di bawah 80%
-- Coba naikkan jadi 15jt (83% dari manager)
UPDATE karyawan
SET gaji = 15000000
WHERE id = 4;
-- ERROR! Gaji staff maksimal 80% dari gaji manager!3.6 Studi Kasus 4: Validasi Perpustakaan
Trigger cek_stok_buku_sebelum_pinjam:
DELIMITER $$
CREATE TRIGGER cek_stok_buku_sebelum_pinjam
BEFORE INSERT ON peminjaman
FOR EACH ROW
BEGIN
DECLARE stok_tersedia INT;
DECLARE judul_buku VARCHAR(200);
-- Ambil stok dan judul buku
SELECT stok, judul INTO stok_tersedia, judul_buku
FROM buku
WHERE id = NEW.buku_id;
-- Validasi 1: Stok harus ada
IF stok_tersedia <= 0 THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = CONCAT('Maaf, buku "', judul_buku, '" sedang kosong!');
END IF;
-- Validasi 2: Anggota tidak boleh meminjam lebih dari 3 buku
DECLARE jumlah_pinjaman_aktif INT;
SELECT COUNT(*) INTO jumlah_pinjaman_aktif
FROM peminjaman
WHERE anggota = NEW.anggota AND status = 'dipinjam';
IF jumlah_pinjaman_aktif >= 3 THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Maaf, maksimal pinjam 3 buku sekaligus!';
END IF;
-- Otomasi 1: Set tgl_pinjam otomatis ke hari ini jika tidak diisi
IF NEW.tgl_pinjam IS NULL THEN
SET NEW.tgl_pinjam = CURDATE();
END IF;
-- Otomasi 2: Status otomatis 'dipinjam'
SET NEW.status = 'dipinjam';
END$$
DELIMITER ;Trigger validasi_pengembalian_buku:
DELIMITER $$
CREATE TRIGGER validasi_pengembalian_buku
BEFORE UPDATE ON peminjaman
FOR EACH ROW
BEGIN
-- Cek kalo status berubah dari dipinjam ke kembali
IF NEW.status = 'kembali' AND OLD.status = 'dipinjam' THEN
-- Otomasi: Set tgl_kembali otomatis ke hari ini
SET NEW.tgl_kembali = CURDATE();
-- Validasi: tgl kembali tidak boleh < tgl pinjam
IF NEW.tgl_kembali < OLD.tgl_pinjam THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = '❌ Tanggal kembali tidak boleh lebih kecil dari tanggal pinjam!';
END IF;
-- Validasi: Hitung denda jika telat (misal: > 14 hari)
DECLARE lama_pinjam INT;
DECLARE denda INT DEFAULT 0;
SET lama_pinjam = DATEDIFF(NEW.tgl_kembali, OLD.tgl_pinjam);
IF lama_pinjam > 14 THEN
SET denda = (lama_pinjam - 14) * 5000; -- Rp 5000 per hari keterlambatan
-- Catat denda (bisa ke tabel lain)
-- Di sini kita cuma kasih warning
SIGNAL SQLSTATE '01000'
SET MESSAGE_TEXT = CONCAT('⚠️ Buku dikembalikan telat ', lama_pinjam-14, ' hari. Denda Rp ', denda);
END IF;
END IF;
END$$
DELIMITER ;Demo Skenario 1: Pinjam buku dengan stok ada
-- Lihat stok buku id=1 (Pemrograman Web) = 5
SELECT * FROM buku WHERE id = 1;
-- Pinjam buku
INSERT INTO peminjaman (buku_id, anggota)
VALUES (1, 'Rina Wijaya');
-- Berhasil! tgl_pinjam otomatis hari ini, status 'dipinjam'
SELECT * FROM peminjaman ORDER BY id DESC LIMIT 1;Demo Skenario 2: Pinjam buku yang stoknya habis
-- Cari buku yang stoknya 0
SELECT * FROM buku WHERE stok = 0;
-- Coba pinjam
INSERT INTO peminjaman (buku_id, anggota)
VALUES (8, 'Test User'); -- Buku id=8 stok=1 (Machine Learning Dasar)
-- ERROR! Maaf, buku "Machine Learning Dasar" sedang kosong!Demo Skenario 3: Anggota meminjam lebih dari 3 buku
-- Rina sudah pinjam 1 buku, coba pinjam lagi sampai 4
INSERT INTO peminjaman (buku_id, anggota) VALUES (2, 'Rina Wijaya'); -- ke-2
INSERT INTO peminjaman (buku_id, anggota) VALUES (3, 'Rina Wijaya'); -- ke-3
-- Coba pinjam ke-4
INSERT INTO peminjaman (buku_id, anggota) VALUES (4, 'Rina Wijaya');
-- ERROR! Maaf, maksimal pinjam 3 buku sekaligus!Demo Skenario 4: Pengembalian buku
-- Lihat peminjaman Rina
SELECT * FROM peminjaman WHERE anggota = 'Rina Wijaya' AND status = 'dipinjam';
-- Kembalikan buku id=1
UPDATE peminjaman
SET status = 'kembali'
WHERE id = 1; -- Sesuaikan ID
-- Berhasil! tgl_kembali otomatis hari ini
SELECT * FROM peminjaman WHERE id = 1;Demo Skenario 5: Pengembalian dengan tanggal yang tidak valid
-- Coba kembalikan dengan tanggal kemarin (manual)
UPDATE peminjaman
SET status = 'kembali', tgl_kembali = '2024-01-01'
WHERE id = 2;
-- ERROR! Tanggal kembali tidak boleh lebih kecil dari tanggal pinjam!3.7 Tabel Ringkasan Trigger Validasi & Otomasi
| Nama Trigger | Tabel | Event | Fungsi Validasi | Fungsi Otomasi |
|---|---|---|---|---|
cek_stok_sebelum_order | orders | BEFORE INSERT | Cek stok cukup, jumlah > 0 | Hitung total harga, set default customer |
cek_karyawan_sebelum_insert | karyawan | BEFORE INSERT | Gaji >= UMR, umur >= 17, nama tidak kosong | Format nama |
validasi_gaji_sebelum_update | karyawan | BEFORE UPDATE | 5 aturan kompleks penggajian | - |
cek_stok_buku_sebelum_pinjam | peminjaman | BEFORE INSERT | Stok > 0, max 3 buku per orang | Set tgl_pinjam, set status |
validasi_pengembalian_buku | peminjaman | BEFORE UPDATE | Tgl kembali >= tgl pinjam | Set tgl_kembali, hitung denda |
3.8 Keuntungan Validasi di Level Database
| Keuntungan | Penjelasan | Contoh |
|---|---|---|
| Tidak Bisa Dilewati | Validasi jalan untuk SEMUA aplikasi | Web, mobile, API, semua kena |
| Konsisten | Aturan yang sama untuk semua | Gaji selalu dicek dengan aturan yang sama |
| Real-time | Validasi terjadi saat itu juga | Stok langsung dicek saat order |
| Mengurangi Bug | Backend tidak perlu mikir validasi | Cukup INSERT, database urus sisanya |
| Keamanan | Mencegah data kotor masuk | Gaji minus? TOLAK! |
3.9 Hal yang Perlu Diperhatikan
- Jangan terlalu banyak validasi → Bisa memperlambat operasi
- Dokumentasikan semua aturan → Supaya tim paham
- Pertimbangkan user experience → Error message harus jelas
- Test semua skenario → Termasuk skenario gagal
- Backup plan → Validasi di aplikasi juga tetap perlu
4. Latihan Praktikum
Exercise 1: Analisis Trigger Validasi
Jalankan query berikut dan analisis hasilnya:
-- 1. Coba insert order dengan jumlah negatif
INSERT INTO orders (product_id, jumlah, customer_name)
VALUES (1, -5, 'Test User');
-- 2. Coba insert karyawan dengan umur 15 tahun
INSERT INTO karyawan (nama, gaji, jabatan, tanggal_lahir, departemen)
VALUES ('Bocil', 4500000, 'Staff', '2011-01-01', 'IT');
-- 3. Coba naikkan gaji staff IT (id=1) jadi 20jt
UPDATE karyawan SET gaji = 20000000 WHERE id = 1;
-- 4. Coba pinjam buku 5 kali berturut-turut untuk anggota yang sama
-- (Gunakan loop atau insert manual)Pertanyaan:
- Error apa yang muncul di setiap skenario?
- Trigger mana yang menangani masing-masing error?
- Menurutmu, apakah validasi ini cukup atau perlu ditambah?
Exercise 2: Buat Validasi Baru
Buat validasi baru di tabel products:
Aturan:
- Harga produk tidak boleh kurang dari Rp 10.000
- Nama produk minimal 3 karakter
- Stok tidak boleh negatif
Langkah:
-- Buat trigger BEFORE INSERT dan BEFORE UPDATE di tabel products
-- Gabungkan semua validasi dalam satu triggerExercise 3: Otomasi Diskon Otomatis
Buat trigger yang otomatis memberikan diskon berdasarkan jumlah pembelian:
Aturan:
- Jika jumlah order >= 10, diskon 10%
- Jika jumlah order >= 20, diskon 15%
- Jika jumlah order >= 50, diskon 20%
Hint: Modifikasi trigger cek_stok_sebelum_order untuk menambahkan logika diskon sebelum menghitung total_harga.
5. Daftar Pustaka
- MySQL Documentation (n.d.). 27.3.1 Trigger Syntax and Examples. https://dev.mysql.com
- MYSQL Tutorial (n.d.). MySQL Triggers. https://www.mysqltutorial.org
- Devart (n.d.). Triggers in MySQL: Definition and How to Use them. https://www.devart.com
- GeeksforGeeks (2025). SQL Create Trigger. https://www.geeksforgeeks.org
- W3Resource (2022). MySQL Triggers. https://www.w3resource.com

0 Komentar