PostgreSQL Trigger

8

Click here to load reader

Transcript of PostgreSQL Trigger

Page 1: PostgreSQL Trigger

Trigger

M. Ammar Shadiq

Ilmu Komputer Universitas Pendidikan Indonesia, Bandung

5 Mei 2008

Catatan :

banyak perintah-perintah pada contoh-contoh berikut yang akan di bahas pada

pembahasan mengenai data integrity.

Pastikan anda telah menginisiasikan procedural language (bahasa prosedural) pada postgreSQL

yang dinamakan PL/pgsql CREATE LANGUAGE plpgsql;

CREATE TRIGGER <nama_trigger>

[BEFORE | AFTER] [ INSERT | DELETE | UPDATE [OR ...]]

ON <nama_table> FOR EACH ROW

EXECUTE PROCEDURE <nama_fungsi> [(args)];

BEFORE

Sebelum mengeksekusi Query pada tabel <nama_table>, jalankan dulu fungsi.

AFTER

Setelah mengeksekusi Query pada tabel <nama_table>, lalu setelah itu jalankan fungsi.

INSERT

Untuk Query yang memasukkan data baru pada tabel <nama_table> jalankan trigger.

DELETE

Untuk Query yang menghapus data pada tabel <nama_table> jalankan trigger.

UPDATE

Untuk Query yang mengubah data pada <nama_table> jalankan trigger.

INSERT OR DELETE

Untuk Query yang memasukkan data baru atau menghapus data pada tabel <nama_table>

jalankan trigger.

INSERT OR DELETE OR UPDATE

Untuk Query yang memasukkan, menghapus atau mengubah data pada tabel <nama_table>

jalankan trigger.

Kemungkinan lainnya penggunaan OR adalah :

INSERT OR UPDATE

DELETE OR UPDATE

Fungsi yang dipanggil Trigger : sebuah fungsi yang di panggil trigger adalah sebuah fungsi yang tidak

memiliki argumen masukan dan argumen keluarannya memiliki tipe data spesial -- TRIGGER.

Fungsi yang di panggil trigger harus mengembalikan nilai NULL atau sebuah record/row yang

memiliki struktur yang sama persis dengan table dimana trigger tersebut ditempatkan.

Page 2: PostgreSQL Trigger

Variabel-variabel spesial trigger PostgreSQL

NEW

Tipe data : RECORD Variabel yang menyimpan record baru untuk operasi INSERT/UPDATE dalam trigger level-

baris(rowlevel). OLD

Tipe data : RECORD Variabel ini menyimpan record lama untuk operasi UPDATE/DELETE dalam trigger level-

baris(rowlevel). TG_NAME

Tipe data : name Variabel ini berisi nama trigger yang dijalankan. TG_WHEN

Tipe data : text

Sebuah string baik dari BEFORE atau AFTER tergantung definisi trigger. TG_OP

Tipe data : text

Sebuah string dari operasi INSERT,UPDATE atau DELETE yang memberitahu untuk operasi mana trigger dijalankan. (digunakan pada Contoh 2) TG_RELID

Tipe data : oid Object ID dari tabel yang menyebabkan pengeksekusian trigger. TG_TABLE_NAME

Tipe data : name Nama tabel yang menyebabkan pengeksekusian trigger. TG_TABLE_SCHEMA

Tipe data : name Nama schema dari tabel yang menyebabkan pengeksekusian trigger. TG_NARGS

Tipe data : integer

Jumlah argumen yang diberikan ke procedure trigger pada statement CREATE TRIGGER TG_ARGV[]

Tipe data : array yang berisi text

Argumen dari statement CREATE TRIGGER. Index mulai dari 0. Pengaksesan dengan index yang

salah (kurang dari 0, lebih besar dari TG_NARGS atau sama dengan TG_NARGS) akan menghasilkan

nilai NULL.

Page 3: PostgreSQL Trigger

Contoh 1 Contoh trigger berikut ini memastikan bahwa tiap kali sebuah baris pada tabel ditambahkan (insert)

atau dirubah (update), username dan waktunya pada saat itu dimasukkan kedalam baris. Trigger ini

juga bekerja untuk mengecek apakah nama pegawai diisikan dan gaji bernilai positif.

CREATE TABLE pegawai1

(

nama_peg text,

gaji_peg integer,

tgl_trkhr timestamp,

user_trkhr text

);

Pertama yang harus dilakukan adalah membuat fungsi yang menjelaskan apa yang dilakukan oleh

trigger tersebut.

CREATE FUNCTION cattn_peg() RETURNS trigger AS $cattn_peg$

BEGIN

-- Periksa nama_peg dan gaji_peg tidak kosong

IF NEW.nama_peg IS NULL THEN

RAISE EXCEPTION 'nama_peg tidak boleh kosong';

END IF;

IF NEW.gaji_peg IS NULL THEN

RAISE EXCEPTION '% gaji_peg tidak boleh kosong', NEW.nama_peg;

END IF;

-- siap yang bekerja untuk kita jika dia yang membayar?

IF NEW.gaji_peg < 0 THEN

RAISE EXCEPTION '% gaji_peg tidak boleh negatif', NEW.nama_peg;

END IF;

-- Tuliskan siap yang mengganti Upah saat itu beserta waktunya

NEW.tgl_trkhr := current_timestamp;

NEW.user_trkhr := current_user;

RETURN NEW;

END;

$cattn_peg$ LANGUAGE 'plpgsql';

Lalu membuat deklarasi trigger yang memanggil fungsi diatas. CREATE TRIGGER cattn_peg BEFORE INSERT OR UPDATE ON pegawai1

FOR EACH ROW EXECUTE PROCEDURE cattn_peg();

Page 4: PostgreSQL Trigger

Contoh 2 Contoh trigger berikut ini memastikan bahwa tiap kali sebuah baris pada tabel pegawai

ditambahkan (insert), dirubah (update) atau dihapus (delete), disimpan catatannya (i.e.

diaudit) pada tabel audit_peg. Yang disimpan adalah waktu dan user name, bersama dengan

operasi yang di lakukan.

CREATE TABLE pegawai2

(

nama_peg text NOT NULL,

gaji_peg integer

);

CREATE TABLE audit_peg1

(

operasi char(1) NOT NULL,

waktu timestamp NOT NULL,

userid text NOT NULL,

nama_peg text NOT NULL,

gaji_peg integer

);

CREATE OR REPLACE FUNCTION proses_audit_peg1() RETURNS TRIGGER AS

$audit_peg1$

BEGIN

--

-- Buat baris (data) pada tabel audit_peg1 untuk merefleksikan operasi

-- yang dilakukan pada tabel pegawai2, menggunakan varibel spesial TG_OP

-- untuk mengoperasikannya.

--

IF (TG_OP = 'DELETE') THEN

INSERT INTO audit_peg1 SELECT 'D', now(), user, OLD.*;

RETURN OLD;

ELSIF (TG_OP = 'UPDATE') THEN

INSERT INTO audit_peg1 SELECT 'U', now(), user, NEW.*;

RETURN NEW;

ELSIF (TG_OP = 'INSERT') THEN

INSERT INTO audit_peg1 SELECT 'I', now(), user, NEW.*;

RETURN NEW;

END IF;

RETURN NULL;

-- hasil diabaikan karena trigger AFTER

END;

$audit_peg1$ LANGUAGE 'plpgsql';

CREATE TRIGGER audit_peg1

AFTER INSERT OR UPDATE OR DELETE ON pegawai2

FOR EACH ROW EXECUTE PROCEDURE proses_audit_peg1();

Keterangan : lihat pada fungsi diatas, baris INSERT INTO .... NEW.*

Page 5: PostgreSQL Trigger

berarti ada 2 kolom yang dimasukkan oleh * yaitu nama_peg dan gaji_peg jadi sebenarnya yang dimasukkan adalah : ‘<huruf>’, <tanggal_sekarang>, <user_yg_mengubah>, <nama_peg> dan <gaji_peg>

Contoh 3 CREATE TABLE pegawai3

(

nama_peg TEXT NOT NULL,

gaji_peg INTEGER,

tgl_dibuat TIMESTAMP NOT NULL,

tgl_diubah TIMESTAMP,

gaji_peg_sblm INTEGER

);

buatlah trigger dengan ketentuan:

1. saat data baru dimasukkan (INSERT), secara otomatis trigger harus memasukkan :

tanggal data di buat (tgl_dibuat).

2. saat suatu data pegawai diubah (UPDATE), data yang harus diisikan adalah :

tanggal data diubah (tgl_diubah) dan

gaji pegawai sebelum diubah (gaji_peg_sblm).

Jawab : CREATE OR REPLACE FUNCTION proses_ubah_gaji() RETURNS TRIGGER AS $$

BEGIN

IF (TG_OP = 'INSERT') THEN

NEW.tgl_dibuat := current_timestamp;

RETURN NEW;

ELSIF (TG_OP = 'UPDATE') THEN

NEW.tgl_diubah := current_timestamp;

NEW.gaji_peg_sblm := OLD.gaji_peg;

RETURN NEW;

END IF;

END;

$$ LANGUAGE 'plpgsql';

CREATE TRIGGER ubah_pegawai BEFORE INSERT OR UPDATE ON pegawai3

FOR EACH ROW EXECUTE PROCEDURE proses_ubah_gaji();

Anda dapat mencobanya dengan perintah :

Insert :

Update :

-- masukkan data pegawai baru dengan nama shadiq dan gaji Rp. 500.000

INSERT INTO pegawai3 (nama_peg, gaji_peg) VALUES ('shadiq', 500000);

-- Lalu lihat data pegawai shadiq yang telah di masukkan

SELECT * FROM pegawai3 WHERE nama_peg = 'shadiq';

Page 6: PostgreSQL Trigger

-- ubah gaji pegawai shadiq menjadi Rp. 1.000.000

UPDATE pegawai3 SET gaji_peg = 1000000 WHERE nama_peg = 'shadiq';

-- Lalu lihat data pegawai shadiq yang telah di ubah

SELECT * FROM pegawai3 WHERE nama_peg = 'shadiq';

Page 7: PostgreSQL Trigger

Contoh 4

CREATE TABLE pegawai4

(

nama_peg text NOT NULL,

gaji integer

);

CREATE TABLE log_pegawai4

(

nama_peg text NOT NULL,

operasi text NOT NULL,

tgl_dibuat timestamp,

tgl_diubah timestamp,

gaji_peg_sekarang integer,

gaji_peg_sebelumnya integer,

selisih_gaji integer

);

buat lah trigger dengan ketentuan :

1. saat meng-insert tabel pegawai4

isi tabel pegawai4_properties dengan nilai : nama_peg : <nama pegawai>

operasi : 'Insert'

tgl_dibuat : <tanggal dan waktu pada saat itu>

gaji_peg_sekarang : <gaji pegawai saat peng-insert-an>

2. saat meng-update tabel pegawai4

isi tabel pegawai4_properties dengan nilai nama_peg : <nama pegawai>

operasi : 'Update'

tgl_diubah : <tanggal dan waktu pada saat itu>

gaji_peg_sebelumnya : <gaji pegawai sebelum datanya di ubah>

gaji_peg_sekarang : <gaji pegawai yang di-update-kan>

selisih_gaji : <selisih gaji sebelum dan setelah datanya di update>

[nilainya selalu positif]

Jawab : CREATE OR REPLACE FUNCTION isi_properties_pegawai4() RETURNS TRIGGER AS

$$

BEGIN

IF(TG_OP = 'INSERT') THEN

INSERT INTO log_pegawai4 (nama_peg, operasi, tgl_dibuat, gaji_peg_sekarang)

VALUES (NEW.nama_peg, TG_OP, NOW(), NEW.gaji);

RETURN NEW;

ELSIF(TG_OP = 'UPDATE') THEN

INSERT INTO log_pegawai4 (nama_peg, operasi, tgl_diubah, gaji_peg_sebelumnya,

gaji_peg_sekarang, selisih_gaji)

VALUES (NEW.nama_peg, TG_OP, NOW(), OLD.gaji, NEW.gaji , ABS(NEW.gaji-

OLD.gaji));

RETURN NEW;

END IF;

END;

$$

LANGUAGE 'plpgsql';

Page 8: PostgreSQL Trigger

CREATE TRIGGER trg_isi_prop_peg4 BEFORE INSERT OR UPDATE ON pegawai4

FOR EACH ROW EXECUTE PROCEDURE isi_properties_pegawai4();

TG_OP Fariabel spesial TG_OP pada PostgreSQL merefleksikan operasi apa yang dilakukan pada suatu tabel.

Namun apa yang terjadi bila berdasarkan kebijakan perusahaan, System Data Base diganti? Tentunya

Trigger-trigger yang telah kita buat belum tentu dapat digunakan lagi, karena pada DBMS lain belum

tentu ada variabel TG_OP pada trigger. solusinya : anda dapat membuat trigger untuk masing-

masing operasi, tentu jumlah trigger menjadi banyak, namun dibayar dengan dipecahkannya

permasalahan kompatibilitas dengan DBMS jenis lain.

Ex :

CREATE TRIGGER trg1_insert BEFORE INSERT ON tabelku

FOR EACH ROW EXECUTE PROCEDURE fungsi1_insert();

CREATE TRIGGER trg2_update BEFORE UPDATE ON tabelku

FOR EACH ROW EXECUTE PROCEDURE fungsi2_update();

CREATE TRIGGER trg2_delete BEFORE DELETE ON tabelku

FOR EACH ROW EXECUTE PROCEDURE fungsi3_delete();