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
ELSE
nhánh chỉ cần gán choNEW
trự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àiIF
cấu trúc sẽ phá vỡ chức năng kích hoạt của bạn choDELETE
, kể từNEW
không được chỉ định cho DELETE. -
Một tính năng chính là sử dụng
hstore
và 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ộnOLD
gố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
hstore
phả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ạohstore
giá 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_datetime
thay vìmod_date
gây hiểu lầm , vì cột rõ ràng là mộtdấu thời gian
và 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();