
Foto oleh panumas nikhomkhai via Pexels
Trigger adalah blok kode yang dijalankan otomatis oleh SQL Server ketika sebuah event tertentu terjadi pada tabel, seperti INSERT, UPDATE, atau DELETE. Berbeda dengan stored procedure yang harus dipanggil secara eksplisit, trigger berjalan sendiri di belakang layar tanpa perlu dipanggil manual oleh aplikasi.
Trigger paling sering dipakai untuk kebutuhan audit (mencatat siapa dan kapan sebuah data diubah), validasi tambahan yang terlalu kompleks untuk CHECK constraint biasa, atau menjaga konsistensi data antar tabel yang saling terkait tanpa mengandalkan aplikasi untuk selalu melakukannya dengan benar.
Meski berguna, trigger juga punya reputasi sebagai sumber bug yang sulit dilacak karena sifatnya yang tersembunyi dari alur kode aplikasi. Artikel ini membahas cara membuat trigger dasar, memahami tabel virtual inserted dan deleted, serta kapan sebaiknya trigger dihindari.
Trigger AFTER INSERT untuk Audit Log
Trigger AFTER INSERT mencatat log otomatis
Memahami Tabel Virtual inserted dan deleted
UPDATE memakai kedua tabel virtual sekaligus
Trigger INSTEAD OF untuk Mengganti Perilaku Default
INSTEAD OF mengganti perilaku DELETE default
Menonaktifkan dan Mengaktifkan Kembali Trigger
DISABLE dan ENABLE TRIGGER untuk kebutuhan sementara
INSTEAD OF Trigger vs AFTER Trigger dan Kasus Penggunaannya
AFTER trigger mencatat audit, INSTEAD OF trigger mengubah perilaku DELETE pada view
AFTER trigger (juga disebut FOR trigger) dieksekusi setelah operasi DML yang memicunya berhasil diterapkan ke tabel, sehingga tabel inserted dan deleted yang tersedia di dalam trigger sudah mencerminkan kondisi data pasca-perubahan; jenis trigger ini hanya bisa dipasang pada tabel, bukan pada view, dan umum dipakai untuk audit trail, validasi lanjutan, atau sinkronisasi ke tabel lain.
INSTEAD OF trigger justru menggantikan sepenuhnya operasi DML asli dengan logika kustom di dalam badan trigger, sehingga pernyataan INSERT, UPDATE, atau DELETE yang memicunya tidak pernah benar-benar dieksekusi terhadap objek target kecuali ditulis ulang secara eksplisit di dalam trigger tersebut. Kemampuan ini membuat INSTEAD OF trigger menjadi satu-satunya cara membuat view yang melibatkan banyak tabel tetap bisa menerima operasi DML secara langsung.
Penggunaan trigger secara berlebihan dapat membuat alur data sulit ditelusuri karena perubahan pada satu tabel bisa memicu efek samping tersembunyi di tabel lain tanpa terlihat jelas pada kode aplikasi, sehingga praktik umum adalah membatasi trigger hanya untuk kebutuhan yang benar-benar tidak bisa dipenuhi di lapisan aplikasi, seperti audit wajib atau enforcement aturan integritas lintas tabel yang kompleks.
Risiko Recursive Trigger dan Cara Mengontrolnya
RECURSIVE_TRIGGERS OFF mencegah trigger memicu dirinya sendiri secara langsung
Recursive trigger terjadi ketika sebuah trigger melakukan operasi DML yang kembali memicu trigger yang sama (direct recursion) atau memicu trigger pada tabel lain yang pada akhirnya mengubah tabel asal (indirect recursion). Pada contoh di atas, trigger AFTER UPDATE pada Employees melakukan UPDATE lagi ke tabel Employees untuk menyinkronkan TeamSize, yang berpotensi memicu dirinya sendiri berulang kali jika opsi rekursi diaktifkan.
SQL Server menyediakan pengaturan database RECURSIVE_TRIGGERS yang secara default OFF, sehingga direct recursion dicegah secara otomatis; namun indirect recursion, yaitu trigger pada tabel A memicu trigger pada tabel B yang kemudian mengubah tabel A lagi, tetap bisa terjadi terlepas dari pengaturan RECURSIVE_TRIGGERS karena pengaturan tersebut hanya mengontrol rekursi langsung pada tabel yang sama. Rantai indirect recursion semacam ini jauh lebih sulit dideteksi karena melibatkan beberapa trigger pada tabel berbeda yang saling terhubung secara tidak langsung.
Untuk mencegah rekursi tak terkendali maupun efek samping berantai yang sulit ditelusuri, praktik yang disarankan adalah menambahkan pengecekan kondisi di awal trigger menggunakan fungsi TRIGGER_NESTLEVEL() untuk mendeteksi apakah trigger sedang dipanggil dari dalam trigger lain, atau merancang ulang logika agar perhitungan seperti TeamSize dilakukan melalui view/computed column daripada menulis ulang tabel yang sama di dalam triggernya sendiri. SQL Server juga membatasi kedalaman nested trigger hingga maksimum 32 level, dan trigger yang melampaui batas ini akan dibatalkan seluruhnya oleh mesin database.
DDL Trigger untuk Mengaudit Perubahan Skema Database
DDL trigger di level DATABASE merekam setiap perubahan struktur tabel
DDL trigger berbeda dari DML trigger karena dipicu oleh pernyataan yang mengubah struktur objek seperti CREATE TABLE, ALTER TABLE, atau DROP TABLE, bukan oleh perubahan data melalui INSERT, UPDATE, atau DELETE. Trigger jenis ini bisa dipasang pada level DATABASE untuk memantau objek di satu database, atau level SERVER untuk memantau perubahan lintas database.
Fungsi EVENTDATA() mengembalikan dokumen XML yang berisi detail lengkap peristiwa DDL yang memicu trigger, termasuk jenis perintah, nama objek yang terpengaruh, dan login yang menjalankannya, sehingga informasi tersebut bisa diekstrak dan disimpan ke tabel audit. Penggunaan umumnya adalah mencegah perubahan skema tanpa persetujuan atau sekadar menjaga jejak audit perubahan struktur database dari waktu ke waktu. DDL trigger juga bisa dipakai bersama ROLLBACK di dalam badan trigger untuk benar-benar memblokir pernyataan DDL tertentu, misalnya menolak DROP TABLE pada jam kerja kecuali dijalankan oleh akun administratif tertentu.
Kesalahan Umum yang Sering Terjadi
Menulis Logika Bisnis Kompleks di Dalam Trigger
Trigger yang berisi logika bisnis rumit membuat alur aplikasi menjadi tidak transparan, karena developer yang membaca kode aplikasi tidak akan tahu ada proses tambahan yang berjalan otomatis di level database kecuali memeriksa trigger secara terpisah.
Lupa Trigger Berjalan per Statement, Bukan per Baris
Trigger di SQL Server berjalan satu kali untuk seluruh statement meski statement tersebut memengaruhi banyak baris sekaligus, sehingga kode yang mengasumsikan hanya satu baris di tabel inserted/deleted akan salah ketika terjadi bulk insert atau bulk update.
Membuat Trigger yang Memanggil Trigger Lain Secara Berantai
Trigger pada satu tabel yang mengubah tabel lain yang juga punya trigger bisa memicu rantai trigger yang sulit dilacak dan berpotensi menyebabkan infinite loop jika tidak dirancang dengan hati-hati.
Kapan Pendekatan Ini Tidak Cocok Dipakai
Trigger sangat berguna untuk memastikan aturan tertentu selalu berlaku tanpa bergantung pada disiplin setiap developer aplikasi untuk mengingatnya, seperti audit log yang harus selalu tercatat apapun cara data diubah.
Namun karena sifatnya yang tersembunyi dan sulit di-debug, banyak tim memilih memindahkan logika yang bisa dipindahkan ke layer aplikasi atau ke stored procedure yang dipanggil secara eksplisit, menyisakan trigger hanya untuk kebutuhan yang benar-benar harus dijamin konsisten di level database.
Ringkasan
Trigger memberi cara untuk menjalankan logika otomatis saat data berubah, dengan tabel virtual inserted dan deleted sebagai kunci untuk mengetahui data sebelum dan sesudah perubahan. Gunakan trigger secukupnya untuk kebutuhan yang memang harus dijamin konsisten di level database, dan hindari menumpuk logika bisnis kompleks di dalamnya.
Seri Belajar SQL Server:
← Sebelumnya: Function pada SQL Server dan Perbedaannya dengan Stored Procedure
→ Selanjutnya: Transaction dan ACID pada SQL Server