PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

INSERT dengan nama tabel dinamis dalam fungsi pemicu

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() atau quote_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 bahwaRETURN OLD; dalam fungsi pemicu diperlukan untuk pemicu BEFORE 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?


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Fitur Kompatibilitas Oracle baru di PostgresPlus Advanced Server 9.3Beta

  2. Bagaimana cara mendeklarasikan variabel lokal di postgresql?

  3. Bagaimana cara mendapatkan data lokal ke dalam database hanya-baca menggunakan dplyr?

  4. Bagaimana cara saya melakukan kueri menggunakan bidang di dalam tipe data PostgreSQL JSON yang baru?

  5. Bagaimana Atan2() Bekerja di PostgreSQL