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

Jalankan kueri tab silang dinamis

Apa yang Anda minta adalah tidak mungkin . SQL adalah bahasa yang diketik dengan ketat. Fungsi PostgreSQL perlu mendeklarasikan tipe pengembalian (RETURNS .. ) pada saat pembuatan .

Cara terbatas untuk mengatasi ini adalah dengan fungsi polimorfik. Jika Anda dapat memberikan jenis pengembalian pada waktu fungsi panggilan . Tapi itu tidak terbukti dari pertanyaan Anda.

  • Memfaktorkan ulang fungsi PL/pgSQL untuk mengembalikan output dari berbagai kueri SELECT

Anda bisa mengembalikan hasil yang sepenuhnya dinamis dengan catatan anonim. Tapi kemudian Anda diminta untuk memberikan daftar definisi kolom dengan setiap panggilan. Dan bagaimana Anda tahu tentang kolom yang dikembalikan? Tangkap 22.

Ada berbagai solusi, tergantung pada apa yang Anda butuhkan atau dapat Anda kerjakan. Karena semua kolom data Anda tampaknya memiliki tipe data yang sama, saya sarankan untuk mengembalikan array :text[] . Atau Anda dapat mengembalikan jenis dokumen seperti hstore atau json . Terkait:

  • Alternatif dinamis untuk pivot dengan CASE dan GROUP BY

  • Ubah kunci hstore secara dinamis menjadi kolom untuk kumpulan kunci yang tidak diketahui

Tetapi mungkin lebih mudah menggunakan dua panggilan:1:Biarkan Postgres membuat kueri. 2:Jalankan dan ambil kembali baris yang dikembalikan.

  • Memilih beberapa nilai max() menggunakan satu pernyataan SQL

Saya tidak akan menggunakan fungsi dari Eric Minikel seperti yang disajikan dalam pertanyaan Anda sama sekali . Itu tidak aman terhadap injeksi SQL dengan cara pengidentifikasi cacat yang berbahaya. Gunakan format() untuk membuat string kueri kecuali Anda menjalankan versi lama yang lebih lama dari Postgres 9.1.

Implementasi yang lebih singkat dan lebih bersih dapat terlihat seperti ini:

CREATE OR REPLACE FUNCTION xtab(_tbl regclass, _row text, _cat text
                              , _expr text  -- still vulnerable to SQL injection!
                              , _type regtype)
  RETURNS text AS
$func$
DECLARE
   _cat_list text;
   _col_list text;
BEGIN

-- generate categories for xtab param and col definition list    
EXECUTE format(
 $$SELECT string_agg(quote_literal(x.cat), '), (')
        , string_agg(quote_ident  (x.cat), %L)
   FROM  (SELECT DISTINCT %I AS cat FROM %s ORDER BY 1) x$$
 , ' ' || _type || ', ', _cat, _tbl)
INTO  _cat_list, _col_list;

-- generate query string
RETURN format(
'SELECT * FROM crosstab(
   $q$SELECT %I, %I, %s
      FROM   %I
      GROUP  BY 1, 2  -- only works if the 3rd column is an aggregate expression
      ORDER  BY 1, 2$q$
 , $c$VALUES (%5$s)$c$
   ) ct(%1$I text, %6$s %7$s)'
, _row, _cat, _expr  -- expr must be an aggregate expression!
, _tbl, _cat_list, _col_list, _type
);

END
$func$ LANGUAGE plpgsql;

Panggilan fungsi yang sama dengan versi asli Anda. Fungsi crosstab() disediakan oleh modul tambahan tablefunc yang harus diinstal. Dasar-dasar:

  • Kueri Tab Silang PostgreSQL

Ini menangani nama kolom dan tabel dengan aman. Perhatikan penggunaan tipe pengenal objek regclass dan regtype . Juga berfungsi untuk nama yang memenuhi syarat skema.

  • Nama tabel sebagai parameter fungsi PostgreSQL

Namun, ini tidak sepenuhnya aman saat Anda meneruskan string untuk dieksekusi sebagai ekspresi (_expr - cellc dalam kueri asli Anda). Jenis input ini pada dasarnya tidak aman terhadap injeksi SQL dan tidak boleh diekspos ke publik umum.

  • Injeksi SQL dalam fungsi Postgres vs kueri yang disiapkan

Memindai tabel hanya sekali untuk kedua daftar kategori dan harus sedikit lebih cepat.

Tetap tidak dapat mengembalikan jenis baris yang sepenuhnya dinamis karena itu sama sekali tidak mungkin.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Hitung jumlah hari antara 2 tanggal di JPA

  2. Apa cara tercepat untuk melakukan penyisipan massal ke Postgres?

  3. Kesalahan sintaks tabel drop postgres

  4. Pengujian Otomatis dari Proses Peningkatan untuk PostgreSQL

  5. Kembali dari fungsi dengan parameter OUT