Jika "sumber" tidak "mengirim pengenal", kolom tidak akan berubah. Maka Anda tidak dapat mendeteksi apakah UPDATE
saat ini dilakukan oleh sumber yang sama dengan yang terakhir atau oleh sumber yang tidak mengubah kolom sama sekali. Dengan kata lain:ini tidak berfungsi dengan baik.
Jika "sumber" dapat diidentifikasi oleh fungsi informasi sesi apa pun, Anda dapat bekerja dengannya. Seperti:
NEW.column = session_user;
Tanpa syarat untuk setiap pembaruan.
Solusi Umum
Saya menemukan cara bagaimana memecahkan masalah aslinya. Kolom akan disetel ke nilai default di apa saja perbarui di mana kolomnya tidak diperbarui (bukan di SET
daftar UPDATE
).
Elemen kunci adalah pemicu per kolom diperkenalkan di PostgreSQL 9.0 - pemicu khusus kolom menggunakan UPDATE OF
column_name
klausa.
Pemicu hanya akan diaktifkan jika setidaknya satu kolom yang terdaftar disebutkan sebagai target
UPDATE
perintah.
Itulah satu-satunya cara sederhana yang saya temukan untuk membedakan apakah kolom telah diperbarui dengan nilai baru yang identik dengan yang lama, atau tidak diperbarui sama sekali.
Satu bisa juga mengurai teks yang dikembalikan oleh current_query()
. Tapi itu tampaknya rumit dan tidak dapat diandalkan.
Fungsi pemicu
Saya menganggap kolom col
didefinisikan NOT NULL
.
Langkah 1: Setel col
ke NULL
jika tidak berubah:
CREATE OR REPLACE FUNCTION trg_tbl_upbef_step1()
RETURNS trigger AS
$func$
BEGIN
IF OLD.col = NEW.col THEN
NEW.col := NULL; -- "impossible" value
END IF;
RETURN NEW;
END
$func$ LANGUAGE plpgsql;
Langkah 2: Kembali ke nilai lama. Pemicu hanya akan diaktifkan, jika nilainya benar-benar diperbarui (lihat di bawah):
CREATE OR REPLACE FUNCTION trg_tbl_upbef_step2()
RETURNS trigger AS
$func$
BEGIN
IF NEW.col IS NULL THEN
NEW.col := OLD.col;
END IF;
RETURN NEW;
END
$func$ LANGUAGE plpgsql;
Langkah 3: Sekarang kita dapat mengidentifikasi pembaruan yang kurang dan menetapkan nilai default sebagai gantinya:
CREATE OR REPLACE FUNCTION trg_tbl_upbef_step3()
RETURNS trigger AS
$func$
BEGIN
IF NEW.col IS NULL THEN
NEW.col := 'default value';
END IF;
RETURN NEW;
END
$func$ LANGUAGE plpgsql;
Pemicu
Pemicu untuk Langkah 2 ditembakkan per kolom!
CREATE TRIGGER upbef_step1
BEFORE UPDATE ON tbl
FOR EACH ROW
EXECUTE PROCEDURE trg_tbl_upbef_step1();
CREATE TRIGGER upbef_step2
BEFORE UPDATE OF col ON tbl -- key element!
FOR EACH ROW
EXECUTE PROCEDURE trg_tbl_upbef_step2();
CREATE TRIGGER upbef_step3
BEFORE UPDATE ON tbl
FOR EACH ROW
EXECUTE PROCEDURE trg_tbl_upbef_step3();
Nama pemicu relevan, karena dijalankan dalam urutan abjad (semuanya BEFORE UPDATE
)!
Prosedurnya dapat disederhanakan dengan sesuatu seperti "pemicu per-bukan-kolom" atau cara lain untuk memeriksa daftar target dari UPDATE
dalam sebuah pemicu. Tapi saya tidak melihat pegangan untuk ini.
Jika col
bisa NULL
, gunakan nilai perantara "mustahil" lainnya dan periksa NULL
tambahan dalam fungsi pemicu 1:
IF OLD.col IS NOT DISTINCT FROM NEW.col THEN
NEW.col := '#impossible_value#';
END IF;
Sesuaikan sisanya.