Thiết lập
Bạn muốn tạo trình kích hoạt (lặp đi lặp lại?) Bằng cách sử dụng cùng một chức năng kích hoạt như được nêu trong câu trả lời liên quan của tôi về dba.SE . Bạn cần chuyển các giá trị cho hàm kích hoạt để tạo nhiều hàng có nhiều giá trị cột, do đó là mảng hai chiều. (Nhưng chúng tôi có thể làm việc với bất kỳ chuỗi được xác định rõ ràng!)
Cách duy nhất để chuyển các giá trị cho một hàm kích hoạt PL / pgSQL (ngoài giá trị cột của hàng kích hoạt) là text
các tham số có thể truy cập bên trong hàm dưới dạng 0- mảng văn bản dựa trên biến mảng đặc biệt TG_ARGV[]
. Bạn có thể chuyển một số lượng tham số khác nhau, nhưng chúng ta đã thảo luận về một chuỗi ký tự đơn đại diện cho mảng 2 chiều của bạn trước đó.
Đầu vào đến từ mảng Python 2 chiều với số nguyên có dấu số, phù hợp với loại Postgres integer
. Sử dụng loại Postgres bigint
để bao gồm các số nguyên không dấu, dưới dạng đã nhận xét
.
Biểu diễn văn bản trong Python trông giống như sau:
[[1,2],[3,4]]
Cú pháp cho một ký tự mảng Postgres:
{{1,2},{3,4}}
Và bạn muốn tự động hóa quy trình.
Tự động hóa hoàn toàn
Bạn có thể nối chuỗi cho CREATE TRIGGER
trong ứng dụng khách của bạn hoặc bạn có thể duy trì logic trong một hàm phía máy chủ và chỉ cần chuyển các tham số.
Trình diễn một hàm ví dụ lấy tên bảng và chuỗi được chuyển cho hàm kích hoạt. Hàm kích hoạt insaft_function()
được xác định trong câu hỏi trước của bạn trên dba.SE
.
CREATE OR REPLACE FUNCTION f_create_my_trigger(_tbl regclass, _arg0 text)
RETURNS void
LANGUAGE plpgsql AS
$func$
BEGIN
EXECUTE format($$
DROP TRIGGER IF EXISTS insaft_%1$s_ids ON %1$s;
CREATE TRIGGER insaft_%1$s_ids
AFTER INSERT ON %1$s
FOR EACH ROW EXECUTE PROCEDURE insaft_function(%2$L)$$
, _tbl
, translate(_arg0, '[]', '{}')
);
END
$func$;
Gọi:
SELECT f_create_my_trigger('measurements', '[[1,2],[3,4]]');
Hoặc:
SELECT f_create_my_trigger('some_other_table', '{{5,6},{7,8}}');
db <> fiddle tại đây
sqlfiddle
cũ
Bây giờ bạn có thể chuyển [[1,2],[3,4]]
(có dấu ngoặc vuông) hoặc {{1,2},{3,4}}
(có dấu ngoặc nhọn). Cả hai đều hoạt động như nhau. translate(_arg0, '[]', '{}'
chuyển dạng đầu tiên thành dạng thứ hai.
Hàm này loại bỏ một trình kích hoạt cùng tên nếu nó tồn tại, trước khi tạo một trình kích hoạt mới. Bạn có thể muốn bỏ hoặc giữ dòng này:
DROP TRIGGER IF EXISTS insaft_%1$s_ids ON %1$s;
Điều này chạy với các đặc quyền của vai trò DB đang gọi. Bạn có thể làm cho nó chạy với các đặc quyền superuser (hoặc bất kỳ khác) nếu cần. Xem:
Có nhiều cách để đạt được điều này. Nó phụ thuộc vào yêu cầu chính xác.
Giải thích format()
format()
và kiểu dữ liệu regclass
giúp nối lệnh DDL một cách an toàn và làm cho việc chèn SQL không thể thực hiện được. Xem:
Đối số đầu tiên là "chuỗi định dạng", tiếp theo là các đối số được nhúng vào chuỗi. Tôi sử dụng báo giá đô la
, điều này không hoàn toàn cần thiết đối với ví dụ này, nhưng nói chung là một ý tưởng hay để nối các chuỗi dài có chứa dấu ngoặc đơn: $$DROP TRIGGER ... $$
format()
được mô hình hóa theo hàm C sprintf
. %1$s
là công cụ định dạng của định dạng format()
hàm số. Nó có nghĩa là đầu tiên (1$
) đối số sau khi chuỗi định dạng được chèn dưới dạng chuỗi không được trích dẫn (%s
), do đó:%1$s
. Đối số đầu tiên để định dạng là _tbl
trong ví dụ - regclass
tham số được hiển thị dưới dạng mã định danh hợp pháp tự động, được trích dẫn kép nếu cần, vì vậy format()
không phải làm thêm. Do đó, chỉ %s
, không phải %I
(định danh). Đọc câu trả lời được liên kết ở trên để biết chi tiết.
Công cụ chỉ định định dạng khác đang được sử dụng là %2$L
:Đối số thứ hai dưới dạng ký tự chuỗi được trích dẫn .
Nếu bạn chưa quen với format()
, hãy chơi với các ví dụ đơn giản sau để hiểu:
SELECT format('input -->|%s|<-- here', '[1,2]')
, format('input -->|%s|<-- here', translate('[1,2]', '[]', '{}'))
, format('input -->|%L|<-- here', translate('[1,2]', '[]', '{}'))
, format('input -->|%I|<-- here', translate('[1,2]', '[]', '{}'));