Struktur dan Sintaks Trigger - Perwira Learning Center


1. Latar Belakang

    Setelah kemarin kita memahami konsep dasar trigger dan melihat berbagai contoh di database plc_trigger_practice, hari ini kita akan mempelajari struktur dan sintaks trigger secara lebih mendalam. Kita akan membedah bagaimana cara membuat trigger, bagian-bagiannya, dan kapan menggunakan BEFORE vs AFTER trigger.

Mengapa ini penting?

  • Memahami sintaks trigger membantu kita membuat trigger sendiri
  • Kita bisa membaca dan memodifikasi trigger yang sudah ada
  • Debugging jadi lebih mudah kalau kita paham struktur trigger

Di database plc_trigger_practice yang sudah kita miliki, ada 11 trigger dengan berbagai fungsi. Mari kita pelajari struktur masing-masing!


2. Alat dan Bahan

a. Perangkat Lunak

  1. MySQL - Database yang sudah terinstall (dari hari sebelumnya)
  2. phpMyAdmin / MySQL Workbench - Tools untuk manage database
  3. VS Code - Untuk menulis query SQL
  4. Database plc_trigger_practice - Yang sudah kita buat kemarin

b. Perangkat Keras

  1. Laptop/PC dengan spesifikasi standar

3. Pembahasan

3.1 Struktur Dasar Trigger

Syntax Dasar CREATE TRIGGER di MySQL:

sql
CREATE TRIGGER nama_trigger
{ BEFORE | AFTER } { INSERT | UPDATE | DELETE }
ON nama_tabel
FOR EACH ROW
BEGIN
    -- Kode SQL yang dijalankan
    -- Bisa akses NEW (data baru) dan OLD (data lama)
END;

Mari kita bedah bagian-bagiannya:

BagianPenjelasanContoh
CREATE TRIGGERKeyword untuk membuat triggerCREATE TRIGGER cek_stok_sebelum_order
BEFORE / AFTERWaktu eksekusiBEFORE INSERT, AFTER UPDATE
INSERT / UPDATE / DELETEEvent yang memicuINSERT ON orders
ON nama_tabelTabel yang dipantauON products
FOR EACH ROWTrigger jalan untuk setiap baris yang terkena dampakWajib ada
BEGIN ... ENDBlok kode yang dijalankanBerisi perintah SQL
NEW.Mengakses data BARU (untuk INSERT/UPDATE)NEW.jumlah, NEW.gaji
OLD.Mengakses data LAMA (untuk UPDATE/DELETE)OLD.stok, OLD.gaji

3.2 NEW vs OLD - Data Lama dan Data Baru

PENTING! NEW dan OLD adalah cara trigger mengakses data:

EventNEW (Data Baru)OLD (Data Lama)
INSERT✅ Ada (data yang dimasukkan)❌ Tidak ada
UPDATE✅ Ada (data setelah update)✅ Ada (data sebelum update)
DELETE❌ Tidak ada✅ Ada (data yang dihapus)

Contoh dari database kita:

sql
-- Trigger UPDATE: Bisa akses NEW dan OLD
CREATE TRIGGER catat_perubahan_gaji
AFTER UPDATE ON karyawan
FOR EACH ROW
BEGIN
    -- OLD.gaji = gaji sebelum diubah
    -- NEW.gaji = gaji setelah diubah
    IF OLD.gaji != NEW.gaji THEN
        INSERT INTO log_gaji VALUES (OLD.id, OLD.gaji, NEW.gaji, NOW(), USER());
    END IF;
END;

3.3 BEFORE vs AFTER - Kapan Trigger Jalan?

Perbedaan utama yang harus dipahami:

AspekBEFORE TRIGGERAFTER TRIGGER
WaktuSebelum data disimpan/diubahSetelah data disimpan/diubah
Bisa batalkan?✅ Bisa pakai SIGNAL SQLSTATE❌ Tidak bisa
Bisa ubah data?✅ Bisa modifikasi NEW❌ Data sudah permanen
Use caseValidasi, perhitungan otomatisLogging, audit trail

Contoh BEFORE Trigger (Validasi):

sql
CREATE TRIGGER cek_stok_sebelum_order
BEFORE INSERT ON orders
FOR EACH ROW
BEGIN
    DECLARE stok_tersedia INT;
    
    SELECT stok INTO stok_tersedia FROM products WHERE id = NEW.product_id;
    
    -- Kalau stok kurang, BATALKAN operasi!
    IF stok_tersedia < NEW.jumlah THEN
        SIGNAL SQLSTATE '45000' 
        SET MESSAGE_TEXT = 'Stok tidak cukup!';
    END IF;
END;

Contoh AFTER Trigger (Logging):

sql
CREATE TRIGGER kurangi_stok_saat_order
AFTER INSERT ON orders
FOR EACH ROW
BEGIN
    -- Data udah masuk, tinggal ngelakuin tindakan lanjutan
    UPDATE products SET stok = stok - NEW.jumlah WHERE id = NEW.product_id;
    
    -- Catat di log (gak bisa nolak order, cuma nyatet)
    INSERT INTO log_stok VALUES (NEW.product_id, ...);
END;

3.4 DELIMITER - Kenapa Harus Diganti?

MASALAH: Di MySQL, titik koma (;) menandakan akhir perintah. Tapi di dalam trigger ada banyak titik koma!

SOLUSI: Ganti delimiter sementara dengan DELIMITER $$

sql
-- Ganti delimiter jadi $$
DELIMITER $$

CREATE TRIGGER nama_trigger
BEFORE INSERT ON tabel
FOR EACH ROW
BEGIN
    -- Perintah 1;
    -- Perintah 2;
    -- Perintah 3;
END$$

-- Kembalikan delimiter ke ;
DELIMITER ;

Contoh dari database kita:

sql
DELIMITER $$

CREATE TRIGGER validasi_gaji_sebelum_update
BEFORE UPDATE ON karyawan
FOR EACH ROW
BEGIN
    DECLARE gaji_direktur DECIMAL(10,2);
    
    -- Validasi 1
    IF NEW.gaji > OLD.gaji * 1.2 THEN
        SIGNAL SQLSTATE '45000' 
        SET MESSAGE_TEXT = 'Kenaikan maksimal 20%';
    END IF;
    
    -- Validasi 2
    IF NEW.jabatan LIKE '%Manager%' THEN
        SELECT gaji INTO gaji_direktur FROM karyawan WHERE jabatan = 'Direktur';
        IF NEW.gaji > gaji_direktur THEN
            SIGNAL SQLSTATE '45000' 
            SET MESSAGE_TEXT = 'Gaji manager tidak boleh lebih dari direktur';
        END IF;
    END IF;
END$$

DELIMITER ;

3.5 SIGNAL SQLSTATE - Membatalkan Operasi

SIGNAL SQLSTATE digunakan untuk membatalkan operasi dan mengembalikan error ke aplikasi.

Syntax:

sql
SIGNAL SQLSTATE '45000' 
SET MESSAGE_TEXT = 'Pesan error yang ditampilkan';

Kenapa pakai '45000'?

  • '45000' adalah kode error umum untuk "unhandled user-defined exception"

  • Bisa diganti dengan kode SQLSTATE lain sesuai kebutuhan

Contoh dari database kita:

sql
-- Cek stok sebelum order
IF stok_tersedia < NEW.jumlah THEN
    SIGNAL SQLSTATE '45000' 
    SET MESSAGE_TEXT = 'Stok tidak cukup, bro!';
END IF;

-- Cek gaji minimal
IF NEW.gaji < 4000000 THEN
    SIGNAL SQLSTATE '45000' 
    SET MESSAGE_TEXT = 'Gaji minimal Rp 4.000.000!';
END IF;

-- Cek tanggal kembali
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;

3.6 Studi Kasus: Semua Trigger di Database Kita

Mari kita analisis semua trigger di database plc_trigger_practice berdasarkan struktur dan fungsinya:

A. Trigger untuk E-Commerce (products & orders)

1. cek_stok_sebelum_order - BEFORE INSERT

sql
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: stok cukup?
    IF stok_tersedia < NEW.jumlah THEN
        SIGNAL SQLSTATE '45000' 
        SET MESSAGE_TEXT = 'Stok tidak cukup, bro!';
    END IF;
    
    -- Hitung total harga otomatis
    SET NEW.total_harga = harga_product * NEW.jumlah;
END;
AnalisisKeterangan
JenisBEFORE INSERT
FungsiValidasi dan perhitungan otomatis
Akses dataNEW (data order baru), SELECT dari products
Bisa batalkan?✅ Ya (SIGNAL jika stok kurang)
Modifikasi data?✅ Ya (SET NEW.total_harga)

2. kurangi_stok_saat_order - AFTER INSERT

sql
CREATE TRIGGER kurangi_stok_saat_order
AFTER INSERT ON orders
FOR EACH ROW
BEGIN
    DECLARE stok_lama INT;
    
    SELECT stok INTO stok_lama FROM products WHERE id = NEW.product_id;
    
    -- Update stok dan terjual
    UPDATE products 
    SET stok = stok - NEW.jumlah,
        terjual = terjual + NEW.jumlah
    WHERE id = NEW.product_id;
    
    -- Catat di log stok
    INSERT INTO log_stok VALUES (...);
END;
AnalisisKeterangan
JenisAFTER INSERT
FungsiUpdate stok dan logging
Akses dataNEW (data order), SELECT dari products
Bisa batalkan?❌ Tidak (udah kejadian)

3. peringatan_stok_menipis - AFTER UPDATE

sql
CREATE TRIGGER peringatan_stok_menipis
AFTER UPDATE ON products
FOR EACH ROW
BEGIN
    -- Stok menipis (<5) dan sebelumnya >=5
    IF NEW.stok < 5 AND OLD.stok >= 5 THEN
        INSERT INTO notifikasi VALUES (... 'warning' ...);
    END IF;
    
    -- Stok habis (0) dan sebelumnya >0
    IF NEW.stok = 0 AND OLD.stok > 0 THEN
        INSERT INTO notifikasi VALUES (... 'danger' ...);
    END IF;
END;
AnalisisKeterangan
JenisAFTER UPDATE
FungsiMembuat notifikasi otomatis
Akses dataNEW (stok baru), OLD (stok lama)
Use caseMonitoring stok

B. Trigger untuk Karyawan (gaji & audit)

4. validasi_gaji_sebelum_update - BEFORE UPDATE

sql
CREATE TRIGGER validasi_gaji_sebelum_update
BEFORE UPDATE ON karyawan
FOR EACH ROW
BEGIN
    DECLARE gaji_direktur DECIMAL(10,2);
    
    -- Rule 1: Kenaikan maksimal 20%
    IF NEW.gaji > OLD.gaji * 1.2 THEN
        SIGNAL SQLSTATE '45000' 
        SET MESSAGE_TEXT = 'Kenaikan maksimal 20%!';
    END IF;
    
    -- Rule 2: Gaji manager <= direktur
    IF NEW.jabatan LIKE '%Manager%' AND NEW.jabatan != 'Direktur' THEN
        SELECT gaji INTO gaji_direktur FROM karyawan WHERE jabatan = 'Direktur';
        IF NEW.gaji > gaji_direktur THEN
            SIGNAL SQLSTATE '45000' 
            SET MESSAGE_TEXT = 'Gaji manager tidak boleh lebih dari direktur!';
        END IF;
    END IF;
END;
AnalisisKeterangan
JenisBEFORE UPDATE
FungsiValidasi aturan bisnis kompleks
Akses dataNEW dan OLD, SELECT dari tabel lain
Bisa batalkan?✅ Ya (SIGNAL jika melanggar aturan)

5. catat_perubahan_gaji - AFTER UPDATE

sql
CREATE TRIGGER catat_perubahan_gaji
AFTER UPDATE ON karyawan
FOR EACH ROW
BEGIN
    -- Catat perubahan gaji
    IF OLD.gaji != NEW.gaji THEN
        INSERT INTO log_gaji VALUES (NEW.id, OLD.gaji, NEW.gaji, NOW(), USER(), 'Update gaji');
    END IF;
    
    -- Catat perubahan jabatan (promosi)
    IF OLD.jabatan != NEW.jabatan THEN
        INSERT INTO log_gaji VALUES (NEW.id, OLD.gaji, NEW.gaji, NOW(), USER(), 
            CONCAT('Promosi dari ', OLD.jabatan, ' ke ', NEW.jabatan));
    END IF;
END;
AnalisisKeterangan
JenisAFTER UPDATE
FungsiAudit trail otomatis
Akses dataNEW dan OLD
KondisionalHanya jalan jika ada perubahan

C. Trigger untuk Perpustakaan (buku & peminjaman)

6. cek_stok_buku_sebelum_pinjam - BEFORE INSERT

sql
CREATE TRIGGER cek_stok_buku_sebelum_pinjam
BEFORE INSERT ON peminjaman
FOR EACH ROW
BEGIN
    DECLARE stok_tersedia INT;
    
    SELECT stok INTO stok_tersedia FROM buku WHERE id = NEW.buku_id;
    
    -- Validasi stok
    IF stok_tersedia <= 0 THEN
        SIGNAL SQLSTATE '45000' 
        SET MESSAGE_TEXT = 'Stok buku kosong!';
    END IF;
    
    -- Set default values
    IF NEW.tgl_pinjam IS NULL THEN
        SET NEW.tgl_pinjam = CURDATE();
    END IF;
    
    SET NEW.status = 'dipinjam';
END;
AnalisisKeterangan
JenisBEFORE INSERT
FungsiValidasi dan set default value
Akses dataNEW (data peminjaman)
Modifikasi data?✅ Ya (SET tgl_pinjam, status)

7. kurangi_stok_buku_saat_pinjam - AFTER INSERT

sql
CREATE TRIGGER kurangi_stok_buku_saat_pinjam
AFTER INSERT ON peminjaman
FOR EACH ROW
BEGIN
    UPDATE buku 
    SET stok = stok - 1,
        dipinjam = dipinjam + 1
    WHERE id = NEW.buku_id;
    
    INSERT INTO log_peminjaman (peminjaman_id, buku_id, anggota, aksi, keterangan)
    VALUES (NEW.id, NEW.buku_id, NEW.anggota, 'PINJAM', 'Peminjaman buku');
END;
AnalisisKeterangan
JenisAFTER INSERT
FungsiUpdate stok dan logging
Akses dataNEW (data peminjaman)

8. validasi_pengembalian_buku - BEFORE UPDATE

sql
CREATE TRIGGER validasi_pengembalian_buku
BEFORE UPDATE ON peminjaman
FOR EACH ROW
BEGIN
    IF NEW.status = 'kembali' AND OLD.status = 'dipinjam' THEN
        SET NEW.tgl_kembali = CURDATE();
        
        IF NEW.tgl_kembali < OLD.tgl_pinjam THEN
            SIGNAL SQLSTATE '45000' 
            SET MESSAGE_TEXT = 'Tanggal kembali tidak valid!';
        END IF;
    END IF;
END;
AnalisisKeterangan
JenisBEFORE UPDATE
FungsiValidasi pengembalian, set tanggal otomatis
Akses dataNEW dan OLD

9. tambah_stok_buku_saat_kembali - AFTER UPDATE

sql
CREATE TRIGGER tambah_stok_buku_saat_kembali
AFTER UPDATE ON peminjaman
FOR EACH ROW
BEGIN
    IF NEW.status = 'kembali' AND OLD.status = 'dipinjam' THEN
        UPDATE buku 
        SET stok = stok + 1,
            dipinjam = dipinjam - 1
        WHERE id = NEW.buku_id;
        
        INSERT INTO log_peminjaman VALUES (..., 'KEMBALI', 'Pengembalian buku');
    END IF;
END;
AnalisisKeterangan
JenisAFTER UPDATE
FungsiUpdate stok saat pengembalian
Akses dataNEW dan OLD
KondisionalHanya jalan saat status berubah

3.7 Melihat Daftar Trigger yang Ada

Query untuk melihat semua trigger di database:

sql
SELECT 
    TRIGGER_NAME AS 'Nama Trigger',
    EVENT_MANIPULATION AS 'Event',
    EVENT_OBJECT_TABLE AS 'Tabel',
    ACTION_TIMING AS 'Timing',
    CREATED AS 'Dibuat'
FROM information_schema.TRIGGERS
WHERE TRIGGER_SCHEMA = 'plc_trigger_practice'
ORDER BY EVENT_OBJECT_TABLE, ACTION_TIMING;

Hasil dari database kita:

text
+-----------------------------------+-------+-------------+--------+
| Nama Trigger                      | Event | Tabel       | Timing |
+-----------------------------------+-------+-------------+--------+
| cek_stok_sebelum_order            | INSERT| orders      | BEFORE |
| kurangi_stok_saat_order           | INSERT| orders      | AFTER  |
| peringatan_stok_menipis           | UPDATE| products    | AFTER  |
| update_timestamp_products         | UPDATE| products    | BEFORE |
| cek_karyawan_sebelum_insert       | INSERT| karyawan    | BEFORE |
| validasi_gaji_sebelum_update      | UPDATE| karyawan    | BEFORE |
| catat_perubahan_gaji              | UPDATE| karyawan    | AFTER  |
| cek_stok_buku_sebelum_pinjam      | INSERT| peminjaman  | BEFORE |
| kurangi_stok_buku_saat_pinjam     | INSERT| peminjaman  | AFTER  |
| validasi_pengembalian_buku         | UPDATE| peminjaman  | BEFORE |
| tambah_stok_buku_saat_kembali      | UPDATE| peminjaman  | AFTER  |
+-----------------------------------+-------+-------------+--------+

3.8 Menghapus Trigger

Syntax:

sql
DROP TRIGGER [IF EXISTS] nama_trigger;

Contoh:

sql
DROP TRIGGER IF EXISTS cek_stok_sebelum_order;

3.9 Tabel Ringkasan Semua Trigger

FungsiBEFOREAFTERContoh
Validasi✅ Cek stok, cek gajicek_stok_sebelum_order
Perhitungan✅ Hitung total hargavalidasi_gaji_sebelum_update
Set Default✅ Set tgl_pinjamcek_stok_buku_sebelum_pinjam
Update Data Lain✅ Kurangi stokkurangi_stok_saat_order
Audit Trail✅ Catat logcatat_perubahan_gaji
Notifikasi✅ Buat notifikasiperingatan_stok_menipis

4. Latihan Praktikum

Exercise 1: Identifikasi Trigger

Lihat trigger validasi_gaji_sebelum_update di database kalian dan jawab:

  1. Termasuk BEFORE atau AFTER?
  2. Event apa yang memicunya?
  3. Data apa yang bisa diakses (NEW, OLD, atau keduanya)?
  4. Apa yang terjadi jika gaji baru lebih dari 20% dari gaji lama?

Exercise 2: Buat Trigger Sederhana

Buat trigger baru untuk tabel products yang:

  1. BEFORE UPDATE: Cek apakah harga baru lebih dari 0
  2. AFTER UPDATE: Catat ke tabel log_stok jika harga berubah

Exercise 3: Analisis Perbedaan

Bandingkan trigger cek_stok_sebelum_order (BEFORE) dan kurangi_stok_saat_order (AFTER):

  1. Apa perbedaan utama fungsi keduanya?
  2. Kenapa kita perlu dua trigger untuk satu operasi INSERT?
  3. Apa yang terjadi jika kita hanya pakai AFTER trigger tanpa BEFORE?

5. Daftar Pustaka

  1. Teknik Elektro Universitas Malang (2016). Modul Praktikum Basis Data - Modul VI Triggerhttps://tei.um.ac.id
  2. Nesabamedia (2022). Mengenal Pengertian Trigger dalam Database Beserta Fungsi dan Contohnya.  https://www.nesabamedia.com
  3. YukCoding (2019). Belajar Trigger di SQl (MySQL)https://yukcoding.id
  4. Liputan6 (2025). Memahami Istilaah "Trigger": Ini Definisi, Jenis, dan Penerapannyahttps://www.liputan6.com
  5. W3Resource (2022). MySQL Triggershttps://www.w3resource.com

Posting Komentar

0 Komentar