Jack telah menunjukkan cara untuk pergi. Namun, saya merasa ada ruang untuk perbaikan.
Saya menempatkan semuanya dalam skema x
untuk pengujian yang mudah. Pengaturan tes:
DROP SCHEMA x CASCADE;
CREATE SCHEMA x;
-- meta tables for schema and table name
CREATE TABLE x.schma(schma_id int, schma text);
INSERT INTO x.schma VALUES (1, 'x');
CREATE TABLE x.tbl(tbl_id int, tbl text);
INSERT INTO x.tbl VALUES (1, 't1'), (2, 't2');
-- dummy tables to be used in example query:
CREATE TABLE x.t1(id int);
INSERT INTO x.t1 VALUES (1),(2);
CREATE TABLE x.t2(foo text);
INSERT INTO x.t2 VALUES ('some text'), ('some more text');
Fungsi lama (jawaban asli):
CREATE OR REPLACE FUNCTION x.f_dynaquery_old(int, int, _col text, _type anyelement, OUT col anyelement)
RETURNS SETOF anyelement AS
$func$
BEGIN
RETURN QUERY EXECUTE '
SELECT ' || quote_ident(_col) || '
FROM ' || (
(SELECT schma FROM schma WHERE schma_id = $1) || '.' ||
(SELECT tbl FROM tbl WHERE tbl_id = $2))::regclass;
END
$func$ LANGUAGE plpgsql;
Versi yang lebih bersih dengan format()
(pembaruan 2017):
CREATE OR REPLACE FUNCTION x.f_dynaquery(_schma_id int, _tbl_id int
, _col text, _type anyelement)
RETURNS TABLE(col anyelement) AS
$func$
BEGIN
RETURN QUERY EXECUTE format(
'SELECT %I FROM %I.%I'
, _col
, (SELECT schma FROM schma WHERE schma_id = _schma_id)
, (SELECT tbl FROM tbl WHERE tbl_id = _tbl_id)
);
END
$func$ LANGUAGE plpgsql;
COMMENT ON FUNCTION x.f_dynaquery(int, int, text, anyelement)
IS 'Query any column from a dynamically assembled tablename.
$1 .. id of schema
$2 .. id of table
$3 .. name of column
$4 .. type of column (only data type matters, not the value)';
Panggilan:
SELECT col FROM x.f_dynaquery(1, 1, 'id', NULL::int);
col
-----
1
2
SELECT col FROM x.f_dynaquery(1, 2, 'foo', NULL::text);
col
----------------
some text
some more text
Poin utama
Fungsi dapat mengembalikan kolom apa pun dari jenis apa pun . Baca di manual tentang Jenis Polimorfik dan Parameter Fungsi Mendeklarasikan .
Pertahankan terhadap injeksi SQL dengan menggunakan quote_ident()
dan melakukan casting keregclass
dalam versi lama atau dengan format()
yang baru. Terkait:
Ambil kembali nama tab berdasarkan permintaan seperti yang diminta OP. Contoh adalah permintaan oleh id
tetapi segala sesuatu mungkin terjadi.
Beri nama kolom yang dikembalikan, sehingga lebih mudah untuk referensi.
Anda memerlukan SQL dinamis - mungkin sesuatu seperti ini:
Saya berasumsi bahwa setiap tabel ada di setiap skema sesuai dengan pertanyaan
sumber