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

Gunakan output teks dari fungsi sebagai kueri baru

Triknya dengan PREPARE tidak berfungsi, karena tidak mengambil * string teks* (nilai) seperti CREATE FUNCTION tidak, tetapi pernyataan yang valid (kode).

Untuk mengonversi data menjadi kode yang dapat dieksekusi anda perlu menggunakan SQL dinamis, yaitu EXECUTE dalam fungsi plpgsql atau DO penyataan. Ini berfungsi tanpa masalah selama tipe pengembalian tidak bergantung pada hasil fungsi pertama myresult() . Kalau tidak, Anda kembali untuk menangkap 22 seperti yang diuraikan dalam jawaban saya sebelumnya:

  • Cara mengeksekusi hasil string dari prosedur tersimpan di postgres

Bagian yang penting adalah mendeklarasikan jenis pengembalian (tipe baris dalam kasus ini) entah bagaimana. Anda dapat membuat TABLE , TEMP TABLE atau TYPE untuk tujuan. Atau Anda dapat menggunakan pernyataan yang sudah disiapkan atau refkursor.

Solusi dengan pernyataan yang sudah disiapkan

Anda sudah sangat dekat. Bagian teka-teki yang hilang adalah menyiapkan kueri yang dihasilkan dengan SQL dinamis .

Fungsi untuk menyiapkan pernyataan secara dinamis

Buat fungsi ini sekali . Ini adalah versi yang dioptimalkan dan aman dari fungsi Anda myresult() :

CREATE OR REPLACE FUNCTION f_prep_query (_tbl regclass, _prefix text)
  RETURNS void AS 
$func$
BEGIN
   IF EXISTS (SELECT 1 FROM pg_prepared_statements WHERE name = 'stmt_dyn') THEN
      DEALLOCATE stmt_dyn;
   END IF;                 -- you my or may not need this safety check 

   EXECUTE (
     SELECT 'PREPARE stmt_dyn AS SELECT '
         || string_agg(quote_ident(attname), ',' ORDER BY attname)
         || ' FROM ' || _tbl
      FROM   pg_catalog.pg_attribute
      WHERE  attrelid = _tbl
      AND    attname LIKE _prefix || '%'
      AND    attnum > 0
      AND    NOT attisdropped
     );
END
$func$  LANGUAGE plpgsql;

Saya menggunakan regclass untuk parameter nama tabel _tbl untuk membuatnya jelas dan aman terhadap SQLi. Detail:

  • Nama tabel sebagai parameter fungsi PostgreSQL

Skema informasi tidak menyertakan kolom oid dari katalog sistem, jadi saya beralih ke pg_catalog.pg_attribute bukannya information_schema.columns . Itu juga lebih cepat. Ada pro dan kontra untuk ini:

  • Cara memeriksa apakah ada tabel dalam skema tertentu

Jika pernyataan disiapkan dengan nama stmt_dyn sudah ada, PREPARE akan menimbulkan pengecualian. Jika itu dapat diterima, hapus centang pada tampilan sistem pg_prepared_statements dan berikut DEALLOCATE .
Algoritme yang lebih canggih dimungkinkan untuk mengelola beberapa pernyataan yang disiapkan per sesi, atau mengambil nama pernyataan yang disiapkan sebagai parameter tambahan, atau bahkan menggunakan hash MD5 dari string kueri sebagai nama, tetapi itu di luar cakupan pertanyaan ini.

Ketahuilah bahwa PREPARE beroperasi di luar cakupan transaksi , sekali PREPARE berhasil, pernyataan yang disiapkan ada untuk seumur hidup sesi. Jika transaksi pembungkus dibatalkan, PREPARE tidak terpengaruh. ROLLBACK tidak bisa hapus pernyataan yang sudah disiapkan.

Eksekusi kueri dinamis

Dua kueri, tetapi hanya satu panggilan ke server. Dan juga sangat efisien.

SELECT f_prep_query('tbl'::regclass, 'pre'::text);
EXECUTE stmt_dyn;

Lebih sederhana dan jauh lebih efisien untuk sebagian besar kasus penggunaan sederhana daripada membuat tabel sementara atau kursor dan memilih/mengambil dari itu (yang akan menjadi opsi lain).

SQL Fiddle.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. instal permata pg tidak berfungsi di OSX Lion

  2. apakah adaptor rails postgres mendukung ssl?

  3. Mengintegrasikan PostgreSQL Dengan Sistem Otentikasi

  4. Mengaktifkan dukungan PostgreSQL di PHP di Mac OS X

  5. Apa Kerangka Ketersediaan Tinggi PostgreSQL Terbaik? Infografis PAF vs. repmgr vs. Patroni