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
ELSEcabang cukup tetapkan keNEWsecara langsung. Tidak perlu SQL yang lebih dinamis - yang akan memicu pemicu yang sama lagi menyebabkan loop tanpa akhir. Itulah kesalahan utama. -
RETURN NEW;di luarIFkonstruksi akan merusak fungsi pemicu Anda untukDELETE, sejakNEWtidak ditetapkan untuk DELETE. -
Fitur utama adalah penggunaan
hstoredan 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 merusakOLDasli 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
hstoreharus 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 membuathstorenilai dengan beberapa bidang dengan cepat. -
Operator penugasan di plpgsql adalah
:=: -
Perhatikan bahwa saya menggunakan nama kolom
mod_datetimebukannyamod_datemisleading yang menyesatkan , karena kolom tersebut jelas merupakantimestampdan 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();