ELSE nhánh có thể được đơn giản hóa hoàn toàn. Nhưng một vài thứ nữa không hiệu quả / không chính xác / nguy hiểm:
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;
-
Trong
ELSEnhánh chỉ cần gán choNEWtrực tiếp. Không cần thêm SQL động - sẽ kích hoạt lại cùng một trình kích hoạt gây ra một vòng lặp vô tận. Đó là lỗi chính. -
TRỞ LẠI MỚI;bên ngoàiIFcấu trúc sẽ phá vỡ chức năng kích hoạt của bạn choDELETE, kể từNEWkhông được chỉ định cho DELETE. -
Một tính năng chính là sử dụng
hstorevà toán tử hstore# =để thay đổi động hai trường đã chọn của loại hàng nổi tiếng - đó là ẩn số tại thời điểm viết mã. Bằng cách này, bạn không làm xáo trộnOLDgốc giá trị, có thể có tác dụng phụ đáng ngạc nhiên nếu bạn có nhiều tác nhân gây ra chuỗi sự kiện hơn.OLD #= hstore('{mod_op, mod_datetime}'::text[] , ARRAY[left(TG_OP, 1), now()::text]);Mô-đun bổ sung
hstorephải được cài đặt. Chi tiết:- Cách đặt giá trị của trường biến hỗn hợp bằng SQL động
- Chuyển động tên cột cho một biến bản ghi trong PostgreSQL
Sử dụng
hstore (text [], text [])biến thể ở đây để tạohstoregiá trị với nhiều trường nhanh chóng. -
Toán tử gán trong plpgsql là
:=: -
Lưu ý rằng tôi đã sử dụng tên cột
mod_datetimethay vìmod_dategây hiểu lầm , vì cột rõ ràng là mộtdấu thời gianvà không phải làngày.
Tôi đã thêm một số cải tiến khác trong khi ở đó. Và bản thân trình kích hoạt sẽ trông như thế này:
CREATE TRIGGER insupdel_bef
BEFORE INSERT OR UPDATE OR DELETE ON table_name
FOR EACH ROW EXECUTE PROCEDURE sample_trigger_func();