Perbedaan Trigger dan Stored Procedure MySQL

| | MySQL (My Structured Query Language)
Perbedaan Trigger dan Stored Procedure MySQL

trigger dan stored procedure adalah objek database yang menyimpan logika SQL. perbedaan utamanya: trigger otomatis, procedure dipanggil manual. sebelum mempelajari ini, pastikan sudah paham cara membuat function di MySQL.

kedua fitur ini dulu sering saya anggap “canggih dan tidak perlu”, sampai ada kebutuhan mencatat setiap perubahan data di tabel secara otomatis. trigger menyelesaikannya tanpa menyentuh kode aplikasi sama sekali. sejak itu saya memahami tempatnya masing-masing: trigger untuk reaksi otomatis, procedure untuk logika yang dipanggil berulang.

1. Perbandingan Lengkap

AspekTriggerStored Procedure
DieksekusiOtomatis (INSERT/UPDATE/DELETE)Manual (CALL)
ParameterTidak punya parameterIN, OUT, INOUT
Return valueTidak adaBanyak (SELECT + OUT)
Bisa dipanggilOtomatis oleh eventCALL nama_procedure()
Jumlah per tabel6 tipe dasar (BEFORE/AFTER x INSERT/UPDATE/DELETE), sejak 5.7.2 bisa banyak per tipe pakai FOLLOWS/PRECEDESTidak terbatas
TransaksiTidak bisa COMMIT/ROLLBACKBisa COMMIT/ROLLBACK
Return resultTidak adaBisa result set
RekursiTidak bisaBisa (dengan hati-hati)
PerformaTambah overhead per eventHanya saat dipanggil

2. Stored Procedure Sederhana

procedure dipanggil manual dengan CALL. cocok untuk logika yang sering dipakai berulang:

DELIMITER //

CREATE PROCEDURE insert_log(aksi VARCHAR(100))
BEGIN
    INSERT INTO logs (aksi, created_at) VALUES (aksi, NOW());
END //

DELIMITER ;

penjelasan per baris:

  • DELIMITER // : ganti delimiter dari ; jadi // sementara. perlu karena di dalam body ada statement yang diakhiri ;.
  • CREATE PROCEDURE insert_log(aksi VARCHAR(100)) : bikin procedure bernama insert_log dengan parameter input aksi varchar 100 karakter.
  • BEGIN ... END : blok body procedure. semua statement SQL di sini.
  • INSERT INTO logs (aksi, created_at) VALUES (aksi, NOW()) : insert ke tabel logs. NOW() fungsi bawaan untuk waktu sekarang.
  • END // : akhir procedure, diakhiri // (delimiter baru).
  • DELIMITER ; : kembalikan delimiter ke ; (default).

cara panggil:

CALL insert_log('User login');
CALL insert_log('User logout');

3. Trigger Sederhana

trigger jalan otomatis setiap ada event di tabel. cocok untuk audit log atau update otomatis:

DELIMITER //

CREATE TRIGGER after_insert_log
AFTER INSERT ON users
FOR EACH ROW
BEGIN
    INSERT INTO logs (aksi, user_id) 
    VALUES ('User baru', NEW.id);
END //

DELIMITER ;

penjelasan per baris:

  • CREATE TRIGGER after_insert_log : bikin trigger dengan nama after_insert_log. convention: prefix dengan timing (after/before) + event.
  • AFTER INSERT ON users : timing (AFTER) dan event (INSERT) di tabel users. bisa juga BEFORE, UPDATE, DELETE.
  • FOR EACH ROW : trigger jalan untuk setiap baris yang ter-insert, bukan per statement.
  • INSERT INTO logs (aksi, user_id) VALUES ('User baru', NEW.id) : insert ke tabel logs. NEW.id adalah id baris baru yang sedang di-insert ke users.
  • NEW dan OLD adalah kata kunci khusus. NEW untuk akses nilai baru (di INSERT/UPDATE), OLD untuk akses nilai lama (di UPDATE/DELETE).

trigger jalan otomatis setiap ada INSERT ke tabel users. tidak perlu dipanggil manual.

4. Perbedaan NEW dan OLD

di dalam trigger, mysql sediakan dua pseudo-row untuk akses data baris yang sedang diproses:

EventOLDNEW
INSERTTidak adaNilai baris baru
UPDATENilai sebelum updateNilai setelah update
DELETENilai baris yang dihapusTidak ada

contoh trigger UPDATE yang pakai keduanya:

DELIMITER //

CREATE TRIGGER after_update_user
AFTER UPDATE ON users
FOR EACH ROW
BEGIN
    INSERT INTO user_changes (user_id, old_name, new_name, changed_at)
    VALUES (OLD.id, OLD.name, NEW.name, NOW());
END //

DELIMITER ;

trigger ini catat perubahan nama user ke tabel audit. OLD.name adalah nama sebelum update, NEW.name adalah nama setelah update.

5. Trigger dengan BEFORE

trigger BEFORE jalan sebelum data masuk/berubah, cocok untuk validasi atau normalisasi:

DELIMITER //

CREATE TRIGGER before_insert_user
BEFORE INSERT ON users
FOR EACH ROW
BEGIN
    -- Normalisasi email ke lowercase
    SET NEW.email = LOWER(NEW.email);
    
    -- Validasi manual: tolak email dari domain terlarang
    IF NEW.email LIKE '%@spam.com' THEN
        SIGNAL SQLSTATE '45000'
        SET MESSAGE_TEXT = 'Email dari domain spam tidak diizinkan';
    END IF;
END //

DELIMITER ;

penjelasan:

  • SET NEW.email = LOWER(NEW.email) : ubah nilai NEW.email sebelum di-insert. karena ini BEFORE, perubahan nilai NEW akan dipakai untuk insert yang sebenarnya.
  • SIGNAL SQLSTATE '45000' : cara trigger melempar error. SQLSTATE 45000 artinya “unhandled user-defined exception”. procedure atau trigger akan berhenti dan rollback.
  • SET MESSAGE_TEXT = '...' : pesan error yang akan dikembalikan ke client.

6. Procedure dengan Parameter OUT

procedure bisa return nilai lewat parameter OUT, cocok untuk ambil data tanpa perlu result set:

DELIMITER //

CREATE PROCEDURE get_user_count(
    IN status_user VARCHAR(20),
    OUT total INT
)
BEGIN
    SELECT COUNT(*) INTO total
    FROM users
    WHERE status = status_user;
END //

DELIMITER ;

cara panggil dari mysql cli:

CALL get_user_count('active', @total);
SELECT @total;
  • parameter IN status_user : input, dikirim dari pemanggil.
  • parameter OUT total : output, diisi di dalam procedure.
  • SELECT COUNT(*) INTO total : ambil hasil count dan simpan ke variabel total.
  • @total : variabel sesi di mysql, dipakai untuk capture nilai OUT.
  • SELECT @total : lihat hasilnya.

7. Procedure dengan INOUT

parameter INOUT gabungan: kirim nilai awal, procedure bisa modifikasi, terima nilai akhir:

DELIMITER //

CREATE PROCEDURE tambah_stok(
    INOUT stok INT,
    IN jumlah INT
)
BEGIN
    SET stok = stok + jumlah;
END //

DELIMITER ;

panggil:

SET @stok = 100;
CALL tambah_stok(@stok, 50);
SELECT @stok;  -- 150

8. Kapan Pakai Apa?

pakai stored procedure ketika:

  • logika bisnis yang sama dipakai di banyak tempat (laporan, batch)
  • butuh parameter input/output
  • ingin sembunyikan kompleksitas SQL dari aplikasi
  • perlu transaksi manual di dalam logika

pakai trigger ketika:

  • butuh reaksi otomatis tanpa modify kode aplikasi
  • audit log perubahan data
  • validasi yang tidak bisa di-handle constraint
  • update otomatis (misal update updated_at, hitung total, sinkronisasi tabel)
  • pertahankan history table (soft delete pattern)

lebih baik jangan pakai keduanya ketika:

  • logika bisa ditulis di kode aplikasi (lebih mudah di-test dan di-debug)
  • overhead trigger/procedure jadi bottleneck performa
  • tim tidak familiar dengan sql procedural (maintenance sulit)

9. Cara Hapus

hapus trigger atau procedure yang sudah tidak dipakai:

-- Hapus trigger
DROP TRIGGER IF EXISTS after_insert_log;

-- Hapus procedure
DROP PROCEDURE IF EXISTS insert_log;

IF EXISTS untuk hindari error kalau objek tidak ada. perlu privilege DROP di database.

10. Informasi Trigger dan Procedure

cara lihat daftar trigger atau procedure di database:

-- Lihat semua procedure
SHOW PROCEDURE STATUS WHERE Db = 'nama_database';

-- Lihat semua trigger
SHOW TRIGGERS;

-- Lihat source code procedure
SHOW CREATE PROCEDURE insert_log;

-- Lihat source code trigger
SHOW CREATE TRIGGER after_insert_log;

berguna untuk debug atau audit. SHOW TRIGGERS tanpa WHERE menampilkan trigger di database yang sedang aktif.

11. Performa dan Best Practice

trigger menambah overhead setiap event. beberapa tips performa:

  • trigger yang kompleks (join tabel, subquery) bisa perlambat insert/update/delete. testing wajib di staging sebelum production.
  • hindari recursive trigger (trigger A picu trigger B yang picu trigger A lagi). bisa deadlock.
  • trigger tidak bisa di-OPTIMIZE atau diindex terpisah. optimalkan tabel yang di-referensi.
  • kalau trigger error, transaksi parent otomatis rollback. pastikan trigger tidak fail untuk kasus normal.

untuk procedure:

  • procedure dengan banyak statement lebih cepat di-serve dari prepared statement.
  • hindari SELECT * di dalam procedure, sebutkan kolom yang dibutuhkan.
  • pisah procedure panjang jadi beberapa procedure kecil yang saling panggil.

Kesimpulan

  • stored procedure : dipanggil manual via CALL, punya parameter IN/OUT/INOUT, bisa return value
  • trigger : otomatis jalan saat INSERT/UPDATE/DELETE, tanpa parameter, tidak bisa return
  • trigger cocok untuk audit log dan sinkronisasi data otomatis
  • procedure cocok untuk bisnis logic dan operasi batch yang berulang
  • NEW untuk akses nilai baru, OLD untuk nilai lama di trigger
  • DELIMITER // wajib di body procedure/trigger yang punya banyak statement
  • SIGNAL SQLSTATE '45000' untuk lempar error dari trigger
  • SHOW TRIGGERS dan SHOW PROCEDURE STATUS untuk lihat daftar
  • trigger menambah overhead performa, test dulu sebelum production

Baca Juga Mengenai :


Pertanyaan yang Sering Diajukan

Apa beda utama trigger dan stored procedure?

trigger jalan otomatis saat ada event INSERT/UPDATE/DELETE, tanpa parameter, tidak bisa return value. stored procedure dipanggil manual pakai CALL, bisa punya parameter IN/OUT/INOUT, bisa return value banyak.

Trigger bisa dipanggil manual seperti procedure?

tidak bisa. trigger hanya jalan otomatis oleh mysql saat event terjadi. kalau mau panggil manual, gunakan stored procedure atau function.

Kenapa harus pakai DELIMITER saat bikin trigger atau procedure?

karena body procedure/trigger berisi banyak statement SQL yang diakhiri titik koma. tanpa DELIMITER, mysql bingung membedakan akhir statement di dalam body dengan akhir statement CREATE PROCEDURE.

Berapa jumlah trigger maksimum per tabel?

secara tipe ada enam (BEFORE/AFTER x INSERT/UPDATE/DELETE). sebelum MySQL 5.7.2 memang maks 1 per tipe, tapi sejak 5.7.2 bisa banyak trigger per tipe yang sama, urutannya diatur pakai FOLLOWS atau PRECEDES.

Apakah trigger bisa transaksi manual?

tidak bisa COMMIT atau ROLLBACK di dalam trigger. trigger jalan dalam transaksi yang sama dengan statement yang memicunya. stored procedure sebaliknya, bisa transaksi manual.

Kapan pakai trigger dan kapan procedure?

trigger untuk reaksi otomatis (audit log, validasi, update timestamp). procedure untuk logika bisnis yang dipanggil berulang (laporan, batch process, hitung total).

Bagaimana cara hapus trigger atau procedure?

DROP TRIGGER nama_trigger; untuk hapus trigger. DROP PROCEDURE nama_procedure; untuk hapus procedure. keduanya perlu privilege DROP di database.

Apakah trigger menurunkan performa?

iya, trigger menambah overhead karena jalan setiap event. untuk query jutaan baris, ini signifikan. testing performa wajib sebelum pakai trigger di production.

Sigit Nurhanafi avatar
Full-stack developer & technical writer. Berpengalaman di PHP, Laravel, NodeJS, MySQL, dan Python. Aktif menulis tutorial pemrograman dan maintaining open-source projects di PemburuKode sejak 2021.