Sebuah pemicu adalah perintah SQL yang telah ditentukan sebelumnya yang dijalankan secara otomatis ketika tindakan tertentu terjadi dalam database. Itu dapat diaktifkan sebelum atau sesudah INSERT
, UPDATE
, atau DELETE
acara.
Pemicu terutama digunakan untuk memelihara logika perangkat lunak di server MySQL, dan memiliki beberapa manfaat:
-
Pemicu membantu menjaga operasi global terpusat di satu lokasi.
-
Mereka mengurangi kode sisi klien dan membantu meminimalkan perjalanan bolak-balik yang dilakukan ke server database.
-
Mereka membantu membuat aplikasi lebih skalabel di berbagai platform.
Beberapa kasus penggunaan pemicu yang umum mencakup pencatatan audit, nilai basis data pra-komputasi (misalnya jumlah kumulatif), dan penegakan aturan integritas dan validasi data yang kompleks.
Dalam panduan ini, Anda akan mempelajari:
-
Bagaimana sintaks untuk pemicu disusun.
-
Cara membuat pemicu yang dieksekusi sebelum kejadian database lainnya terjadi.
-
Cara membuat pemicu yang dieksekusi setelah kejadian database lain terjadi.
-
Cara menghapus pemicu.
Sebelum Anda Mulai
-
Jika Anda belum melakukannya, buat akun Linode dan Compute Instance. Lihat panduan Memulai Linode dan Membuat Instans Komputasi.
-
Ikuti panduan Menyiapkan dan Mengamankan Instans Komputasi untuk memperbarui sistem Anda. Anda mungkin juga ingin mengatur zona waktu, mengkonfigurasi nama host Anda, membuat akun pengguna terbatas, dan memperkuat akses SSH.
-
Server dan klien MySQL diinstal pada server Linode. Panduan penginstalan untuk MySQL tersedia untuk distribusi yang berbeda di bagian MySQL kami.
Siapkan Database
Untuk lebih memahami cara kerja pemicu, kami akan membuat database sampel dan menambahkan data sampel ke dalamnya. Nanti, kita akan membuat trigger yang berbeda pada database sebagai bukti latihan konsep.
-
Pertama, masuk ke Server MySQL Anda:
mysql -u root -p
Kemudian, masukkan kata sandi root server MySQL Anda dan tekan Enter untuk melanjutkan.
-
Selanjutnya, Anda akan melihat prompt MySQL yang mirip dengan yang ditunjukkan di bawah ini:
mysql >
-
Buat
test_database
dengan menjalankan perintah di bawah ini:CREATE DATABASE test_database;
Keluaran:
Query OK, 1 row affected (0.02 sec)
-
Beralih ke database:
USE test_database;
Keluaran:
Database changed
-
Setelah database dipilih, kita akan membuat beberapa tabel yang akan kita gunakan untuk mendemonstrasikan trigger. Kita akan mulai dengan membuat
stores
meja. Tabel ini akan menyimpan informasi tentang dua toko/kantor sampel tempat bisnis hipotetis kami beroperasi:CREATE TABLE stores ( store_id BIGINT PRIMARY KEY AUTO_INCREMENT, store_name VARCHAR(50) ) ENGINE=InnoDB;
Keluaran:
Query OK, 0 rows affected (0.07 sec)
-
Selanjutnya, tambahkan dua record ke
stores
tabel dengan menjalankan perintah di bawah ini:INSERT INTO stores (store_name) VALUES ('Philadelphia'); INSERT INTO stores (store_name) VALUES ('Galloway');
Setelah setiap perintah, Anda akan mendapatkan output di bawah ini:
Query OK, 1 row affected (0.08 sec) ...
-
Konfirmasikan catatan dengan menjalankan perintah di bawah ini:
SELECT * FROM stores;
Keluaran:
+----------+--------------+ | store_id | store_name | +----------+--------------+ | 1 | Philadelphia | | 2 | Galloway | +----------+--------------+ 2 rows in set (0.01 sec)
-
Selanjutnya, buat
products
meja. Tabel akan berisi berbagai produk yang ditawarkan di toko:CREATE TABLE products ( product_id BIGINT PRIMARY KEY AUTO_INCREMENT, product_name VARCHAR(40), cost_price DOUBLE, retail_price DOUBLE, availability VARCHAR(5) ) ENGINE=InnoDB;
Keluaran:
Query OK, 0 rows affected (0.13 sec)
-
Setiap produk akan diidentifikasi secara unik dengan
product_id
. -
product_name
field akan menentukan nama item. -
cost_price
danretail_price
kolom akan menentukan harga beli dan harga jual masing-masing. -
Sebuah
availability
kolom akan menentukan ketersediaan produk di toko yang berbeda. Jika produk hanya tersedia di toko lokal kami (Philadelphia), kami akan menandainya denganLOCAL
nilai. Jika tidak, kita akan menggunakan nilaiALL
untuk menandakan produk yang tersedia di kedua toko (Philadelphia dan Galloway).
-
-
Tambahkan data sampel ke
products
tabel:INSERT INTO products (product_name, cost_price, retail_price, availability) VALUES ('WIRELESS MOUSE', '18.23', '30.25','ALL'); INSERT INTO products (product_name, cost_price, retail_price, availability) VALUES ('8 MP CAMERA', '60.40', '85.40','ALL'); INSERT INTO products (product_name, cost_price, retail_price, availability) VALUES ('SMART WATCH', '189.60', '225.30','LOCAL');
Anda akan mendapatkan output yang ditunjukkan di bawah ini setelah setiap memasukkan perintah:
Query OK, 1 row affected (0.02 sec) ...
-
Konfirmasikan apakah produk telah dimasukkan dengan menjalankan perintah di bawah ini:
SELECT * FROM products;
Keluaran:
+------------+----------------+------------+--------------+--------------+ | product_id | product_name | cost_price | retail_price | availability | +------------+----------------+------------+--------------+--------------+ | 1 | WIRELESS MOUSE | 18.23 | 30.25 | ALL | | 2 | 8 MP CAMERA | 60.4 | 85.4 | ALL | | 3 | SMART WATCH | 189.6 | 225.3 | LOCAL | +------------+----------------+------------+--------------+--------------+ 3 rows in set (0.00 sec)
-
Selanjutnya, ketersediaan produk akan dipetakan ke tabel lain bernama
products_to_stores
. Tabel ini hanya akan mereferensikanproduct_id
dariproducts
tabel danstore_id
daristores
tabel tempat item tersedia.Buat
products_to_stores
tabel dengan menjalankan kode di bawah ini:CREATE TABLE products_to_stores ( ref_id BIGINT PRIMARY KEY AUTO_INCREMENT, product_id BIGINT, store_id BIGINT ) ENGINE=InnoDB;
Keluaran:
Query OK, 0 rows affected (0.14 sec)
-
Selanjutnya, kita akan membuat
archived_products
meja. Tabel akan menyimpan informasi tentang produk yang dihapus untuk referensi di masa mendatang:CREATE TABLE archived_products ( product_id BIGINT PRIMARY KEY , product_name VARCHAR(40), cost_price DOUBLE, retail_price DOUBLE, availability VARCHAR(5) ) ENGINE=InnoDB;
Keluaran:
Query OK, 0 rows affected (0.14 sec)
-
Terakhir, kita akan membuat
products_price_history
tabel untuk melacak harga yang berbeda dari setiap produk dari waktu ke waktu:CREATE TABLE products_price_history ( product_id BIGINT PRIMARY KEY AUTO_INCREMENT, price_date DATETIME, retail_price DOUBLE ) ENGINE=InnoDB;
Keluaran:
Query OK, 0 rows affected (0.14 sec)
Setelah struktur database kami siap, sekarang kami dapat melanjutkan dan mempelajari sintaks dasar pemicu database MySQL untuk membuat sampel pertama kami.
Sintaks Pemicu
Seperti yang ditunjukkan sebelumnya, pemicu diaktifkan secara otomatis sebelum atau setelah perintah SQL dijalankan di database. Sintaks dasar untuk membuat pemicu adalah sebagai berikut:
CREATE TRIGGER TRIGGER_NAME
TRIGGER_TIME TRIGGER_EVENT
ON TABLE_NAME FOR EACH ROW
[TRIGGER BODY];
-
TRIGGER_NAME
:Setiap pemicu harus memiliki nama unik dan Anda harus mendefinisikannya di sini. -
TRIGGER_TIME
:BaikBEFORE
atauAFTER
. -
TRIGGER_EVENT
:Anda perlu menentukan kejadian database yang akan memanggil pemicu:INSERT
,UPDATE
, atauDELETE
. -
TRIGGER BODY
:Ini menentukan perintah SQL aktual (atau perintah) yang ingin Anda jalankan oleh pemicu Anda.
Jika badan pemicu memiliki lebih dari satu pernyataan SQL, Anda harus menyertakannya dalam BEGIN...END
memblokir. Selain itu, Anda perlu mengubah sementara DELIMITER
yang menandakan akhir dari tubuh pemicu ke nilai baru. Ini memastikan bahwa pernyataan di dalam tubuh tidak ditafsirkan secara prematur oleh klien MySQL Anda. Contohnya seperti berikut ini:
DELIMITER &&
CREATE TRIGGER TRIGGER_NAME
TRIGGER_TIME TRIGGER_EVENT
ON TABLE_NAME FOR EACH ROW
BEGIN
[TRIGGER BODY]
END &&
DELIMITER ;
Catatan Baris terakhir dari contoh ini mengubahDELIMITER
kembali ke default;
nilai.
Membuat Sebelum Pemicu Peristiwa
Di bagian ini, kita akan melihat berbagai jenis pemicu yang dipicu sebelum operasi database. Ini termasuk BEFORE INSERT
, BEFORE UPDATE
, dan BEFORE DELETE
pemicu.
Membuat Pemicu Sebelum Sisipan
Kami akan membuat BEFORE INSERT
pertama kami pemicu. Pemicu akan memastikan bahwa harga eceran suatu produk lebih besar dari harga pokok setiap kali item dimasukkan ke dalam products
meja. Jika tidak, pengguna database akan mendapatkan kesalahan.
-
Saat masih di
mysql >
prompt, masukkan perintah di bawah ini:DELIMITER $$ CREATE TRIGGER price_validator BEFORE INSERT ON products FOR EACH ROW IF NEW.cost_price>=NEW.retail_price THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Retail price must be greater than cost price.'; END IF $$ DELIMITER ;
-
Kode di atas mendefinisikan nama pemicu (
price_validator
), waktu (BEFORE
), peristiwa (INSERT
), dan tabel (products
) yang akan terpengaruh. -
Pemicu kami menggunakan
NEW
kata kunci untuk memeriksacost_price
danretail_price
sebelum record dimasukkan keproducts
tabel, menggunakanIF...THEN...END IF
pernyataan. -
Jika
cost_price
lebih besar atau sama denganretail price
, pemicu kami memberi tahu MySQL untuk mengeluarkan pengecualian khusus yang menginstruksikan pengguna untuk memperbaiki kesalahan.
-
-
Untuk menguji pemicu di atas, coba masukkan produk yang melanggar aturan validasi:
INSERT INTO products (product_name, cost_price, retail_price, availability) VALUES ('GAMING MOUSE PAD', '145.00', '144.00','LOCAL');
Keluaran:
ERROR 1644 (45000): Retail price must be greater than cost price.
Perintah insert di atas seharusnya gagal karena
retail_price
(144.00) tidak lebih besar daricost_price
(145.00).
Membuat Pemicu Sebelum Pembaruan
Selanjutnya, kita akan membuat BEFORE UPDATE
pemicu. Pemicu ini akan mencegah pengguna database mengedit nama produk setelah produk dimasukkan ke dalam database. Jika Anda memiliki beberapa pengguna yang bekerja di database, BEFORE UPDATE
trigger dapat digunakan untuk membuat nilai hanya-baca, dan ini dapat mencegah pengguna yang jahat atau ceroboh dari memodifikasi catatan yang tidak perlu.
-
Buat
product_name_validator
baru pemicu dengan perintah di bawah ini:DELIMITER $$ CREATE TRIGGER product_name_validator BEFORE UPDATE ON products FOR EACH ROW IF NEW.product_name<>OLD.product_name THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Product name is read-only and it can not be changed.'; END IF $$ DELIMITER ;
Pemicu ini membandingkan nilai
product_name
baru (NEW.product_name
) dan nama lama sudah ada di database (OLD.product_name
). Jika ada ketidakcocokan, pengecualian dilemparkan. -
Untuk memanggil
product_name_validator
pemicu, kami dapat mencoba memperbarui nama produk dengan ID1
:UPDATE products SET product_name='WIRELESS BLUETOOTH MOUSE' WHERE product_id='1';
Keluaran:
ERROR 1644 (45000): Product name is read-only and it can not be changed.
Mendefinisikan Pemicu Sebelum Menghapus
Di bagian ini, Anda akan melihat bagaimana Anda dapat menentukan BEFORE DELETE
pemicu untuk mencegah pengguna menghapus catatan tertentu dari tabel.
-
Untuk membuat
prevent_delete
pemicu, jalankan perintah di bawah ini:DELIMITER $$ CREATE TRIGGER prevent_delete BEFORE DELETE ON products FOR EACH ROW IF OLD.availability='ALL' THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'The product can not be deleted because it is available in ALL stores.'; END IF $$ DELIMITER ;
Pemicu ini akan mencegah produk yang ditandai dengan nilai
ALL
di kolom ketersediaan agar tidak dihapus. -
Selanjutnya, coba hapus produk pertama dari tabel produk dan lihat apakah pemicu akan dipanggil:
DELETE FROM products WHERE product_id='1';
Keluaran:
ERROR 1644 (45000): The product can not be deleted because it is available in ALL stores.
Kami telah melihat berbagai pemicu yang dipanggil sebelum operasi database. Selanjutnya, kita akan melihat jenis pemicu lain yang dipicu setelah peristiwa basis data.
Membuat Pemicu Setelah Acara
Di lingkungan produksi, Anda mungkin ingin beberapa pemicu dijalankan secara otomatis setelah kejadian database terjadi (misalnya, menyisipkan rekaman ke dalam tabel yang berbeda). Contoh di bawah ini menunjukkan bagaimana jenis pemicu ini dapat digunakan dalam database sampel kami.
Membuat Pemicu Setelah Sisipan
Contoh ini membuat pemicu bernama product_availability
yang menyisipkan catatan pemetaan ke dalam products_to_stores
meja. Pemicu ini digunakan untuk menegakkan logika bisnis; khususnya, ini membantu menentukan ketersediaan produk untuk toko yang berbeda.
-
Jalankan kode di bawah ini untuk membuat
product_availability
pemicu. Karena kami memiliki beberapa baris kode di badan pemicu, kami akan menggunakanBEGIN...END
blok:DELIMITER $$ CREATE TRIGGER product_availability AFTER INSERT ON products FOR EACH ROW BEGIN IF NEW.availability='LOCAL' then INSERT INTO products_to_stores (product_id, store_id) VALUES (NEW.product_id, '1'); ELSE INSERT INTO products_to_stores (product_id, store_id) VALUES (NEW.product_id, '1'); INSERT INTO products_to_stores (product_id, store_id) VALUES (NEW.product_id, '2'); END IF; END $$ DELIMITER ;
-
Saat item dimasukkan ke dalam
products
tabel, pemicu akan memeriksaavailability
lapangan. -
Jika ditandai dengan
LOCAL
nilai, produk hanya akan tersedia di satu toko. -
Nilai lain apa pun akan menginstruksikan pemicu untuk membuat produk tersedia di dua toko yang kita buat sebelumnya.
-
-
Untuk melihat
product_availability
pemicu beraksi, masukkan dua catatan ke tabel produk:INSERT INTO products (product_name, cost_price, retail_price, availability) VALUES ('BLUETOOTH KEYBOARD', '17.60', '23.30','LOCAL'); INSERT INTO products (product_name, cost_price, retail_price, availability) VALUES ('DVB-T2 RECEIVE', '49.80', '53.40','ALL');
-
Kemudian, kueri
products_to_stores
tabel:SELECT * FROM products_to_stores;
Anda akan melihat output yang mirip dengan yang ditunjukkan di bawah ini:
+--------+------------+----------+ | ref_id | product_id | store_id | +--------+------------+----------+ | 1 | 4 | 1 | | 2 | 5 | 1 | | 3 | 5 | 2 | +--------+------------+----------+ 3 rows in set (0.00 sec)
Mendefinisikan Pemicu Setelah Pembaruan
Pemicu juga dapat diaktifkan setelah UPDATE
peristiwa. Kami akan melihat bagaimana kami dapat memanfaatkan jenis pemicu ini untuk melacak perubahan harga di toko kami dari waktu ke waktu.
-
Buat
product_history_updater
memicu dengan menjalankan perintah di bawah ini:CREATE TRIGGER product_history_updater AFTER UPDATE ON products FOR EACH ROW INSERT INTO products_price_history (product_id, price_date, retail_price) VALUES (OLD.product_id, NOW(), NEW.retail_price);
Pemicu ini mencatat perubahan pada
retail_price
produk diproducts_price_history
tabel.Catatan Tidak seperti contoh sebelumnya, pemicu ini hanya memiliki satu pernyataan di isi pemicu, jadi kita tidak perlu mengubah
DELIMITER
. -
Kemudian, coba update harga produk pertama dengan menjalankan perintah di bawah ini:
UPDATE products SET retail_price='36.75' WHERE product_id='1';
-
Selanjutnya, kueri
products_price_history
tabel untuk melihat apakah perubahan harga telah dicatat:SELECT * FROM products_price_history;
Jika pemicu bekerja seperti yang diharapkan, Anda akan mendapatkan output di bawah ini:
+------------+---------------------+--------------+ | product_id | price_date | retail_price | +------------+---------------------+--------------+ | 1 | 2020-01-28 11:46:21 | 36.75 | +------------+---------------------+--------------+ 1 row in set (0.00 sec)
Membuat Pemicu Setelah Penghapusan
Dalam beberapa kasus, Anda mungkin ingin mencatat operasi penghapusan setelah tindakan tertentu terjadi di database. Anda dapat mencapai ini dengan menggunakan AFTER DELETE
pemicu.
-
Buat
product_archiver
baru pemicu dengan perintah di bawah ini:CREATE TRIGGER product_archiver AFTER DELETE ON products FOR EACH ROW INSERT INTO archived_products (product_id, product_name, cost_price, retail_price, availability) VALUES (OLD.product_id, OLD.product_name, OLD.cost_price, OLD.retail_price, OLD.availability);
Pemicu ini mengarsipkan produk yang dihapus dalam tabel terpisah bernama
archived_products
. Saat item dihapus dariproducts
utama tabel, pemicu kami akan secara otomatis mencatatnya kearchived_products
tabel untuk referensi di masa mendatang. -
Selanjutnya, hapus produk dari
products
tabel dan lihat apakah pemicu akan dipanggil:DELETE FROM products WHERE product_id='3';
-
Sekarang, jika Anda memeriksa
archived_products
tabel, Anda akan melihat satu record:SELECT * FROM archived_products;
Keluaran:
+------------+--------------+------------+--------------+--------------+ | product_id | product_name | cost_price | retail_price | availability | +------------+--------------+------------+--------------+--------------+ | 3 | SMART WATCH | 189.6 | 225.3 | LOCAL | +------------+--------------+------------+--------------+--------------+ 1 row in set (0.00 sec)
Menghapus Pemicu
Anda telah melihat berbagai jenis pemicu dan bagaimana pemicu tersebut dapat digunakan dalam lingkungan produksi. Terkadang, Anda mungkin ingin menghapus pemicu dari database.
Anda dapat menghapus pemicu jika Anda tidak ingin menggunakannya lagi menggunakan sintaks di bawah ini:
DROP TRIGGER IF EXISTS TRIGGER_NAME;
Catatan IF EXISTS
kata kunci adalah parameter opsional yang hanya menghapus pemicu jika ada.
Misalnya, untuk menghapus product_archiving
pemicu yang kami definisikan di atas, gunakan perintah di bawah ini:
DROP TRIGGER IF EXISTS product_archiver;
Keluaran:
Query OK, 0 rows affected (0.00 sec)
Hati-hati Berhati-hatilah saat menghapus tabel yang terkait dengan pemicu. Setelah tabel dikeluarkan dari database MySQL, pemicu terkait juga akan dihapus secara otomatis.
Informasi Lebih Lanjut
Anda mungkin ingin berkonsultasi dengan sumber daya berikut untuk informasi tambahan tentang topik ini. Meskipun ini disediakan dengan harapan dapat bermanfaat, harap perhatikan bahwa kami tidak dapat menjamin keakuratan atau ketepatan waktu materi yang dihosting secara eksternal.
- Sintaks dan Contoh Pemicu MySQL