PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

Thực thi trình kích hoạt hoãn lại chỉ một lần trên mỗi hàng trong PostgreSQL

Đây là một vấn đề khó. Nhưng nó có thể được thực hiện với trình kích hoạt mỗi cột và thực thi trình kích hoạt có điều kiện được giới thiệu trong PostgreSQL 9.0 .

Bạn cần cờ "cập nhật" trên mỗi hàng cho giải pháp này. Sử dụng boolean cột trong cùng một bảng cho đơn giản. Nhưng nó có thể nằm trong một bảng khác hoặc thậm chí là một bảng tạm thời cho mỗi giao dịch.

Tải trọng đắt tiền được thực thi một lần trên mỗi hàng nơi cập nhật bộ đếm (một lần hoặc nhiều lần).

Điều này cũng sẽ thực hiện tốt, bởi vì ...

  • ... nó tránh nhiều lệnh gọi của trình kích hoạt ở gốc (tỷ lệ tốt)
  • ... không làm thay đổi các hàng bổ sung (giảm thiểu sự cồng kềnh của bảng)
  • ... không cần xử lý ngoại lệ tốn kém.

Hãy xem xét những điều sau

Bản trình diễn

Đã kiểm tra trong PostgreSQL 9.1 với một lược đồ riêng biệt x làm môi trường thử nghiệm.

Bảng và hàng giả

-- DROP SCHEMA x;
CREATE SCHEMA x;

CREATE TABLE x.tbl (
 id int
,counter int
,trig_exec_count integer  -- for monitoring payload execution.
,updated bool);

Chèn hai hàng để chứng minh nó hoạt động với nhiều hàng:

INSERT INTO x.tbl VALUES
 (1, 0, 0, NULL)
,(2, 0, 0, NULL);

Chức năng trình kích hoạt và Trình kích hoạt

1.) Thực hiện tải trọng đắt tiền

CREATE OR REPLACE FUNCTION x.trg_upaft_counter_change_1()
    RETURNS trigger AS
$BODY$
BEGIN

 -- PERFORM some_expensive_procedure(NEW.id);
 -- Update trig_exec_count to count execution of expensive payload.
 -- Could be in another table, for simplicity, I use the same:

UPDATE x.tbl t
SET    trig_exec_count = trig_exec_count + 1
WHERE  t.id = NEW.id;

RETURN NULL;  -- RETURN value of AFTER trigger is ignored anyway

END;
$BODY$ LANGUAGE plpgsql;

2.) Gắn cờ hàng được cập nhật.

CREATE OR REPLACE FUNCTION x.trg_upaft_counter_change_2()
    RETURNS trigger AS
$BODY$
BEGIN

UPDATE x.tbl
SET    updated = TRUE
WHERE  id = NEW.id;
RETURN NULL;

END;
$BODY$ LANGUAGE plpgsql;

3.) Đặt lại cờ "đã cập nhật".

CREATE OR REPLACE FUNCTION x.trg_upaft_counter_change_3()
    RETURNS trigger AS
$BODY$
BEGIN

UPDATE x.tbl
SET    updated = NULL
WHERE  id = NEW.id;
RETURN NULL;

END;
$BODY$ LANGUAGE plpgsql;

Tên kích hoạt có liên quan! Được gọi cho cùng một sự kiện, chúng được thực thi theo thứ tự bảng chữ cái.

1.) Tải trọng, chỉ khi chưa được "cập nhật":

CREATE CONSTRAINT TRIGGER upaft_counter_change_1
    AFTER UPDATE OF counter ON x.tbl
    DEFERRABLE INITIALLY DEFERRED
    FOR EACH ROW
    WHEN (NEW.updated IS NULL)
    EXECUTE PROCEDURE x.trg_upaft_counter_change_1();

2.) Gắn cờ hàng là đã cập nhật, chỉ khi chưa được "cập nhật":

CREATE TRIGGER upaft_counter_change_2   -- not deferred!
    AFTER UPDATE OF counter ON x.tbl
    FOR EACH ROW
    WHEN (NEW.updated IS NULL)
    EXECUTE PROCEDURE x.trg_upaft_counter_change_2();

3.) Đặt lại cờ. Không có vòng lặp vô tận vì điều kiện kích hoạt.

CREATE CONSTRAINT TRIGGER upaft_counter_change_3
    AFTER UPDATE OF updated ON x.tbl
    DEFERRABLE INITIALLY DEFERRED
    FOR EACH ROW
    WHEN (NEW.updated)                 --
    EXECUTE PROCEDURE x.trg_upaft_counter_change_3();

Kiểm tra

Chạy UPDATE &SELECT riêng biệt để xem hiệu ứng hoãn lại. Nếu được thực hiện cùng nhau (trong một giao dịch), SELECT sẽ hiển thị tbl.counter mới nhưng tbl2.trig_exec_count cũ .

UPDATE x.tbl SET counter = counter + 1;

SELECT * FROM x.tbl;

Bây giờ, hãy cập nhật bộ đếm nhiều lần (trong một lần giao dịch). Tải trọng sẽ chỉ được thực hiện một lần. Voilá!

UPDATE x.tbl SET counter = counter + 1;
UPDATE x.tbl SET counter = counter + 1;
UPDATE x.tbl SET counter = counter + 1;
UPDATE x.tbl SET counter = counter + 1;
UPDATE x.tbl SET counter = counter + 1;

SELECT * FROM x.tbl;


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. LOWER LIKE so với iLIKE

  2. Cách giảm thiểu RPO cho cơ sở dữ liệu PostgreSQL của bạn bằng cách sử dụng phục hồi tại thời điểm

  3. Có cách nào để tải dữ liệu văn bản vào cơ sở dữ liệu trong PostgreSQL không?

  4. Tham gia bên trong &tham gia bên ngoài; thứ tự của các bảng trong từ có quan trọng không?

  5. Chuyển các tham số IN WHERE cho Dạng xem PostgreSQL?