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:
- Nama tabel sebagai Parameter fungsi PostgreSQL
- Perbaiki fungsi PL/pgSQL untuk mengembalikan output dari berbagai kueri SELECT
- Pemeran tipe data postgres
- Cara menetapkan nilai bidang variabel komposit menggunakan SQL dinamis
- Cara memeriksa apakah ada tabel dalam skema tertentu
- Pilih kolom dengan nama kolom tertentu di PostgreSQL
- Hasilkan rangkaian tanggal - gunakan tipe tanggal sebagai input
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 ...