Penyiapan
Anda ingin membuat pemicu (berulang kali?) menggunakan fungsi pemicu yang sama seperti yang dijelaskan dalam jawaban terkait saya di dba.SE . Anda harus meneruskan nilai ke fungsi pemicu untuk membuat banyak baris dengan banyak nilai kolom, maka array dua dimensi. (Tapi kita bisa bekerja dengan apa saja string yang jelas!)
Satu-satunya cara untuk meneruskan nilai ke fungsi pemicu PL/pgSQL (selain nilai kolom dari baris pemicu) adalah text
parameter, yang dapat diakses di dalam fungsi sebagai 0- array berbasis teks dalam variabel array khusus TG_ARGV[]
. Anda dapat melewatkan sejumlah variabel parameter, tetapi kita telah membahas literal string tunggal yang mewakili larik 2 dimensi Anda sebelumnya.
Input berasal dari larik Python 2 dimensi dengan integer bertanda angka, yang cocok dengan tipe Postgres integer
. Gunakan jenis Postgres bigint
untuk menutupi nomor integer yang tidak ditandatangani, sebagai dikomentari
.
Representasi teks dalam Python terlihat seperti ini:
[[1,2],[3,4]]
Sintaks untuk literal array Postgres:
{{1,2},{3,4}}
Dan Anda ingin mengotomatiskan prosesnya.
Otomasi penuh
Anda dapat menggabungkan string untuk CREATE TRIGGER
pernyataan di klien Anda atau Anda dapat mempertahankan logika dalam fungsi sisi server dan hanya meneruskan parameter.
Mendemonstrasikan fungsi contoh dengan mengambil nama tabel dan string yang diteruskan ke fungsi pemicu. Fungsi pemicu insaft_function()
didefinisikan dalam pertanyaan Anda sebelumnya di 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$;
Telepon:
SELECT f_create_my_trigger('measurements', '[[1,2],[3,4]]');
Atau:
SELECT f_create_my_trigger('some_other_table', '{{5,6},{7,8}}');
db<>fiddle di sini
Lama sqlfiddle
Sekarang Anda dapat melewati [[1,2],[3,4]]
(dengan tanda kurung siku) atau {{1,2},{3,4}}
(dengan kurung kurawal). Keduanya bekerja sama. translate(_arg0, '[]', '{}'
mengubah bentuk pertama menjadi bentuk kedua.
Fungsi ini menjatuhkan pemicu dengan nama yang sama jika ada, sebelum membuat yang baru. Anda mungkin ingin menghapus atau mempertahankan baris ini:
DROP TRIGGER IF EXISTS insaft_%1$s_ids ON %1$s;
Ini berjalan dengan hak istimewa dari peran DB pemanggil. Anda dapat menjalankannya dengan hak pengguna super (atau lainnya) jika perlu. Lihat:
Ada banyak cara untuk mencapai ini. Itu tergantung pada persyaratan yang tepat.
Menjelaskan format()
format()
dan tipe data regclass
membantu untuk menggabungkan perintah DDL dengan aman dan membuat injeksi SQL menjadi tidak mungkin. Lihat:
Argumen pertama adalah "format string", diikuti oleh argumen yang akan disematkan dalam string. Saya menggunakan dollar-quoting
, yang tidak sepenuhnya diperlukan untuk contoh, tetapi umumnya ide yang baik untuk menggabungkan string panjang yang berisi tanda kutip tunggal:$$DROP TRIGGER ... $$
format()
dimodelkan di sepanjang fungsi C sprintf
. %1$s
adalah penentu format dari format format()
fungsi. Artinya yang pertama (1$
) argumen setelah string format dimasukkan sebagai string tanpa tanda kutip (%s
), maka:%1$s
. Argumen pertama untuk memformat adalah _tbl
dalam contoh - regclass
parameter dirender sebagai pengenal hukum secara otomatis, tanda kutip ganda jika perlu, jadi format()
tidak harus berbuat lebih banyak. Karenanya cukup %s
, bukan %I
(pengidentifikasi). Baca jawaban tertaut di atas untuk detailnya.
Penentu format lain yang digunakan adalah %2$L
:Argumen kedua sebagai literal string yang dikutip .
Jika Anda baru mengenal format()
, mainkan dengan contoh sederhana ini untuk memahami:
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]', '[]', '{}'));
Dan baca manual .