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

CHÈN với tên bảng động trong chức năng kích hoạt

PostgreSQL 9.1 trở lên

format() có một cách tích hợp để thoát khỏi số nhận dạng. Đơn giản hơn trước:

CREATE OR REPLACE FUNCTION foo_before()
  RETURNS trigger AS
$func$
BEGIN
   EXECUTE format('INSERT INTO %I.%I SELECT $1.*'
                , TG_TABLE_SCHEMA, TG_TABLE_NAME || 'shadow')
   USING OLD;

   RETURN OLD;
END
$func$  LANGUAGE plpgsql;

Hoạt động với VALUES cả biểu thức.

db <> fiddle here
Sqlfiddle cũ.

Những điểm chính

  • Sử dụng format() hoặc quote_ident() để trích dẫn số nhận dạng (tự động và chỉ khi cần thiết), do đó bảo vệ khỏi việc đưa vào SQL và vi phạm cú pháp đơn giản.
    Điều này là cần thiết , ngay cả với tên bảng của riêng bạn!
  • Lược đồ xác định điều kiện cho tên bảng. Tùy thuộc vào search_path hiện tại Nếu không, việc đặt một tên bảng trống có thể giải quyết cho một bảng khác có cùng tên trong một giản đồ khác.
  • Sử dụng EXECUTE cho các câu lệnh DDL động.
  • Chuyển các giá trị an toàn với USING mệnh đề.
  • Tham khảo hướng dẫn chi tiết về Thực thi các lệnh động trong plpgsql.
  • Lưu ý rằng RETURN OLD; trong hàm kích hoạt là bắt buộc đối với trình kích hoạt BEFORE DELETE . Chi tiết trong sách hướng dẫn tại đây.

Bạn nhận được thông báo lỗi trong phiên bản gần như thành công của bạn vì OLD không hiển thị bên trong EXECUTE . Và nếu bạn muốn nối các giá trị riêng lẻ của hàng đã phân tách như bạn đã thử, bạn phải chuẩn bị biểu diễn văn bản của mỗi cột đơn với quote_literal() để đảm bảo cú pháp hợp lệ. Bạn cũng sẽ phải biết trước các tên cột để xử lý chúng hoặc truy vấn danh mục hệ thống - điều này đi ngược lại ý tưởng của bạn về việc có một chức năng kích hoạt động, đơn giản ...

Giải pháp của tôi tránh được tất cả những biến chứng này. Cũng được đơn giản hóa một chút.

PostgreSQL 9.0 trở xuống

format() vẫn chưa có sẵn, vì vậy:

CREATE OR REPLACE FUNCTION foo_before()
  RETURNS trigger AS
$func$
BEGIN
    EXECUTE 'INSERT INTO ' || quote_ident(TG_TABLE_SCHEMA)
                    || '.' || quote_ident(TG_TABLE_NAME || 'shadow')
                    || ' SELECT $1.*'
    USING OLD;

    RETURN OLD;
END
$func$  LANGUAGE plpgsql;

Có liên quan:

  • Cách sử dụng động TG_TABLE_NAME trong PostgreSQL 8.2?


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cập nhật nhiều hàng trong cùng một truy vấn bằng PostgreSQL

  2. Cách tự động hóa PostgreSQL 12 sao chép và chuyển đổi dự phòng với repmgr - Phần 2

  3. Ràng buộc thả PostgreSQL với tên không xác định

  4. Sự hiểu biết về hoạt động hàng loạt của JDBC

  5. Lưu trữ đầu ra của truy vấn đã chọn trong một mảng trong postgres