PostgreSQL 9.1 atau lebih baru
format()
memiliki cara bawaan untuk menghindari pengidentifikasi. Lebih sederhana dari sebelumnya:
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;
Bekerja dengan VALUES
ekspresi juga.
db<>main biola di sini
sqlfiddle lama.
Poin utama
- Gunakan
format()
atauquote_ident()
untuk mengutip pengidentifikasi (secara otomatis dan hanya jika diperlukan), dengan demikian melindungi dari injeksi SQL dan pelanggaran sintaksis sederhana.
Ini perlu , bahkan dengan nama tabel Anda sendiri! - Skema-kualifikasi nama tabel. Tergantung pada
search_path
saat ini menyetel nama tabel kosong mungkin sebaliknya menyelesaikan ke tabel lain dengan nama yang sama dalam skema yang berbeda. - Gunakan
EXECUTE
untuk pernyataan DDL dinamis. - Luluskan nilai aman dengan
USING
klausa. - Lihat manual yang bagus tentang Menjalankan Perintah Dinamis di plpgsql.
- Perhatikan bahwa
RETURN OLD;
dalam fungsi pemicu diperlukan untuk pemicuBEFORE DELETE
. Detailnya ada di manual di sini.
Anda mendapatkan pesan kesalahan dalam versi Anda yang hampir berhasil karena OLD
tidak terlihat di dalam EXECUTE
. Dan jika Anda ingin menggabungkan nilai individual dari baris yang didekomposisi seperti yang Anda coba, Anda harus menyiapkan representasi teks dari setiap kolom dengan quote_literal()
untuk menjamin sintaks yang valid. Anda juga harus tahu nama kolom sebelumnya untuk menanganinya atau menanyakan katalog sistem - yang bertentangan dengan ide Anda untuk memiliki fungsi pemicu dinamis yang sederhana ...
Solusi saya menghindari semua komplikasi ini. Juga sedikit disederhanakan.
PostgreSQL 9.0 atau sebelumnya
format()
belum tersedia, jadi:
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;
Terkait:
- Bagaimana cara menggunakan TG_TABLE_NAME secara dinamis di PostgreSQL 8.2?