Nếu "nguồn" không "gửi số nhận dạng", cột sẽ không thay đổi. Sau đó, bạn không thể phát hiện xem UPDATE
hiện tại hay không được thực hiện bởi cùng một nguồn như nguồn cuối cùng hoặc bởi một nguồn hoàn toàn không thay đổi cột. Nói cách khác:điều này không hoạt động đúng cách.
Nếu "nguồn" có thể được xác định bởi bất kỳ chức năng thông tin phiên nào, bạn có thể làm việc với điều đó. Như:
NEW.column = session_user;
Vô điều kiện cho mọi bản cập nhật.
Giải pháp chung
Tôi đã tìm ra cách giải quyết vấn đề ban đầu. Cột sẽ được đặt thành giá trị mặc định trong bất kỳ cập nhật nơi cột không được cập nhật (không có trong SET
danh sách UPDATE
).
Yếu tố chính là trình kích hoạt mỗi cột được giới thiệu trong PostgreSQL 9.0 - trình kích hoạt cột cụ thể bằng cách sử dụng UPDATE OF
column_name
mệnh đề.
Trình kích hoạt sẽ chỉ kích hoạt nếu ít nhất một trong các cột được liệt kê được đề cập là mục tiêu của
UPDATE
lệnh.
Đó là cách đơn giản duy nhất mà tôi tìm thấy để phân biệt liệu một cột đã được cập nhật với giá trị mới giống với giá trị cũ hay không được cập nhật.
Một có thể cũng phân tích cú pháp văn bản được trả về bởi current_query()
. Nhưng điều đó có vẻ phức tạp và không đáng tin cậy.
Các chức năng kích hoạt
Tôi giả sử một cột col
định nghĩa NOT NULL
.
Bước 1: Đặt col
thành NULL
nếu không thay đổi:
CREATE OR REPLACE FUNCTION trg_tbl_upbef_step1()
RETURNS trigger AS
$func$
BEGIN
IF OLD.col = NEW.col THEN
NEW.col := NULL; -- "impossible" value
END IF;
RETURN NEW;
END
$func$ LANGUAGE plpgsql;
Bước 2: Hoàn nguyên về giá trị cũ. Trình kích hoạt sẽ chỉ được kích hoạt, nếu giá trị thực sự được cập nhật (xem bên dưới):
CREATE OR REPLACE FUNCTION trg_tbl_upbef_step2()
RETURNS trigger AS
$func$
BEGIN
IF NEW.col IS NULL THEN
NEW.col := OLD.col;
END IF;
RETURN NEW;
END
$func$ LANGUAGE plpgsql;
Bước 3: Bây giờ, chúng tôi có thể xác định bản cập nhật thiếu và đặt giá trị mặc định thay thế:
CREATE OR REPLACE FUNCTION trg_tbl_upbef_step3()
RETURNS trigger AS
$func$
BEGIN
IF NEW.col IS NULL THEN
NEW.col := 'default value';
END IF;
RETURN NEW;
END
$func$ LANGUAGE plpgsql;
Trình kích hoạt
Trình kích hoạt cho Bước 2 được kích hoạt trên mỗi cột!
CREATE TRIGGER upbef_step1
BEFORE UPDATE ON tbl
FOR EACH ROW
EXECUTE PROCEDURE trg_tbl_upbef_step1();
CREATE TRIGGER upbef_step2
BEFORE UPDATE OF col ON tbl -- key element!
FOR EACH ROW
EXECUTE PROCEDURE trg_tbl_upbef_step2();
CREATE TRIGGER upbef_step3
BEFORE UPDATE ON tbl
FOR EACH ROW
EXECUTE PROCEDURE trg_tbl_upbef_step3();
Tên trình kích hoạt có liên quan, bởi vì chúng được kích hoạt theo thứ tự bảng chữ cái (tất cả đều là BEFORE UPDATE
)!
Quy trình có thể được đơn giản hóa với một cái gì đó như "trình kích hoạt mỗi cột" hoặc bất kỳ cách nào khác để kiểm tra danh sách mục tiêu của một UPDATE
trong một trình kích hoạt. Nhưng tôi thấy không có cách nào cho việc này.
Nếu col
có thể là NULL
, sử dụng bất kỳ giá trị trung gian "không thể" nào khác và kiểm tra NULL
bổ sung trong chức năng kích hoạt 1:
IF OLD.col IS NOT DISTINCT FROM NEW.col THEN
NEW.col := '#impossible_value#';
END IF;
Điều chỉnh phần còn lại cho phù hợp.