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

Trong một hàm kích hoạt, cách lấy các trường nào đang được cập nhật

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.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Mẹo điều chỉnh hiệu suất PostgreSQL

  2. K-Nearest Neighbor Query trong PostGIS

  3. LỖI PostgreSQL:hủy tuyên bố do xung đột với khôi phục

  4. Chế độ ngủ đông lưu Mô hình người dùng vào Postgres

  5. Khóa chính tổng hợp trong django