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

Menjalankan kueri secara dinamis di PL/pgSQL

Statistik sistem

Sebelum Anda menggulung sendiri, lihat tabel sistem pg_statistic atau lihat pg_stats :

Mungkin sudah memiliki beberapa statistik yang akan Anda hitung. Itu diisi oleh ANALYZE , jadi Anda dapat menjalankannya untuk tabel baru (atau apa pun) sebelum memeriksanya.

-- ANALYZE tbl;  -- optionally, to init / refresh
SELECT * FROM pg_stats
WHERE tablename = 'tbl'
AND   schemaname = 'public';

Fungsi plpgsql dinamis generik

Anda ingin mengembalikan nilai minimum untuk setiap kolom dalam tabel tertentu . Ini bukan tugas sepele, karena fungsi (seperti SQL pada umumnya) menuntut untuk mengetahui tipe kembalian pada waktu pembuatan - atau setidaknya pada waktu panggilan dengan bantuan tipe data polimorfik.

Fungsi ini melakukan semuanya secara otomatis dan aman. Bekerja untuk apa saja tabel, selama fungsi agregat min() diperbolehkan untuk setiap kolom. Tapi Anda membutuhkan untuk mengetahui cara Anda menggunakan PL/pgSQL.

CREATE OR REPLACE FUNCTION f_min_of(_tbl anyelement)
  RETURNS SETOF anyelement
  LANGUAGE plpgsql AS
$func$
BEGIN
RETURN QUERY EXECUTE (
   SELECT format('SELECT (t::%2$s).* FROM (SELECT min(%1$s) FROM %2$s) t'
                , string_agg(quote_ident(attname), '), min(' ORDER BY attnum)
                , pg_typeof(_tbl)::text)
   FROM   pg_attribute
   WHERE  attrelid = pg_typeof(_tbl)::text::regclass
   AND    NOT attisdropped  -- no dropped (dead) columns
   AND    attnum > 0        -- no system columns
   );
END
$func$;

Telepon (penting!):

SELECT * FROM f_min_of(NULL::tbl);  -- tbl being the table name

db<>fiddle di sini
Lama sqlfiddle

Anda perlu memahami konsep-konsep ini:

  • SQL Dinamis dalam plpgsql dengan EXECUTE
  • Jenis polimorfik
  • Tipe baris dan tipe tabel di Postgres
  • Cara bertahan dari injeksi SQL
  • Fungsi gabungan
  • Katalog sistem

Jawaban terkait dengan penjelasan rinci:

Kesulitan khusus dengan ketidakcocokan jenis

Saya memanfaatkan Postgres yang mendefinisikan tipe baris untuk setiap tabel yang ada. Dengan menggunakan konsep tipe polimorfik, saya dapat membuat satu fungsi yang berfungsi untuk tabel apa pun.

Namun, beberapa fungsi agregat mengembalikan tipe data yang terkait tetapi berbeda dibandingkan dengan kolom yang mendasarinya. Misalnya, min(varchar_column) mengembalikan text , yang sedikit kompatibel, tetapi tidak persis tipe data yang sama. Fungsi PL/pgSQL memiliki titik lemah di sini dan bersikeras pada tipe data tepatnya seperti yang dinyatakan dalam RETURNS ayat. Tidak ada upaya untuk mentransmisikan, bahkan tidak ada pemeran implisit, apalagi tentang pemeran penugasan.

Itu harus ditingkatkan. Diuji dengan Postgres 9.3. Tidak menguji ulang dengan 9.4, tapi saya cukup yakin, tidak ada yang berubah di area ini.

Di situlah konstruksi ini berperan sebagai solusi :

SELECT (t::tbl).* FROM (SELECT ... FROM tbl) t;

Dengan mentransmisikan seluruh baris ke tipe baris dari tabel yang mendasarinya secara eksplisit, kami memaksa pemeran penugasan untuk mendapatkan tipe data asli untuk setiap kolom.

Ini mungkin gagal untuk beberapa fungsi agregat. sum() mengembalikan numeric untuk sum(bigint_column) untuk mengakomodasi jumlah yang melebihi tipe data dasar. Mentransmisikan kembali ke bigint mungkin gagal ...



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Postgres:Bisakah kita memiliki kolom kenaikan otomatis di kunci komposit?

  2. ActiveRecord::StatementInvalid, PG::UndefinedTable error, tetapi SQL yang dihasilkan berfungsi

  3. Bagaimana cara menggunakan fungsi PostgreSQL upper() dengan lokal yang berbeda?

  4. bagaimana cara melakukan kurang dari atau sama dengan dan lebih besar dari sama dengan di filter Django?

  5. Cara membaca dari .mdb 32 bit dengan python 64 bit dan driver odbc