ELSE
cabang dapat disederhanakan secara radikal. Tetapi beberapa hal lagi tidak efisien / tidak akurat / berbahaya:
CREATE OR REPLACE FUNCTION sample_trigger_func()
RETURNS TRIGGER AS
$func$
BEGIN
IF TG_OP = 'DELETE' THEN
RAISE INFO 'OLD: %', OLD.name;
EXECUTE format('INSERT INTO %I SELECT ($1).*', TG_TABLE_NAME || '_deletes')
USING OLD #= hstore('{mod_op, mod_datetime}'::text[]
, ARRAY[left(TG_OP, 1), now()::text]);
RETURN OLD;
ELSE -- insert, update
NEW.mod_op := left(TG_OP, 1);
NEW.mod_datetime := now();
RETURN NEW;
END IF;
END
$func$ LANGUAGE plpgsql;
-
Dalam
ELSE
cabang cukup tetapkan keNEW
secara langsung. Tidak perlu SQL yang lebih dinamis - yang akan memicu pemicu yang sama lagi menyebabkan loop tanpa akhir. Itulah kesalahan utama. -
RETURN NEW;
di luarIF
konstruksi akan merusak fungsi pemicu Anda untukDELETE
, sejakNEW
tidak ditetapkan untuk DELETE. -
Fitur utama adalah penggunaan
hstore
dan operator hstore#=
untuk secara dinamis mengubah dua bidang yang dipilih dari jenis baris terkenal - itu tidak diketahui pada saat penulisan kode. Dengan cara ini Anda tidak merusakOLD
asli nilai, yang mungkin memiliki efek samping yang mengejutkan jika Anda memiliki lebih banyak pemicu dalam rangkaian peristiwa.OLD #= hstore('{mod_op, mod_datetime}'::text[] , ARRAY[left(TG_OP, 1), now()::text]);
Modul tambahan
hstore
harus dipasang. Detail:- Cara menetapkan nilai bidang variabel komposit menggunakan SQL dinamis
- Meneruskan nama kolom secara dinamis untuk variabel record di PostgreSQL
Menggunakan
hstore(text[], text[])
varian di sini untuk membuathstore
nilai dengan beberapa bidang dengan cepat. -
Operator penugasan di plpgsql adalah
:=
: -
Perhatikan bahwa saya menggunakan nama kolom
mod_datetime
bukannyamod_date
misleading yang menyesatkan , karena kolom tersebut jelas merupakantimestamp
dan bukandate
.
Saya menambahkan beberapa peningkatan lain saat melakukannya. Dan pemicunya sendiri akan terlihat seperti ini:
CREATE TRIGGER insupdel_bef
BEFORE INSERT OR UPDATE OR DELETE ON table_name
FOR EACH ROW EXECUTE PROCEDURE sample_trigger_func();